1 salcianu 1.1.2.1 // MetaCallGraphImpl.java, created Wed Mar 8 15:20:29 2000 by salcianu 2 cananian 1.1.2.27 // 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.25 import java.util.Arrays; 7 salcianu 1.1.2.1 import java.util.Map; 8 salcianu 1.1.2.1 import java.util.HashMap; 9 salcianu 1.1.2.1 import java.util.Set; 10 salcianu 1.1.2.1 import java.util.HashSet; 11 salcianu 1.5 import java.util.List; 12 salcianu 1.5 import java.util.LinkedList; 13 salcianu 1.1.2.1 import java.util.Iterator; 14 salcianu 1.5 import java.util.Collection; 15 salcianu 1.1.2.1 import java.util.Collections; 16 salcianu 1.1.2.1 17 salcianu 1.1.2.1 import java.lang.reflect.Modifier; 18 salcianu 1.1.2.1 19 salcianu 1.1.2.1 import harpoon.Analysis.ClassHierarchy; 20 salcianu 1.1.2.1 import harpoon.Analysis.ReachingDefs; 21 salcianu 1.1.2.1 import harpoon.Analysis.ReachingDefsImpl; 22 salcianu 1.7 import harpoon.Analysis.SSxReachingDefsImpl; 23 salcianu 1.1.2.1 import harpoon.Analysis.BasicBlock; 24 salcianu 1.1.2.1 import harpoon.ClassFile.HCodeElement; 25 salcianu 1.1.2.28 import harpoon.ClassFile.HCodeFactory; 26 salcianu 1.1.2.28 import harpoon.ClassFile.CachingCodeFactory; 27 salcianu 1.1.2.1 import harpoon.ClassFile.HMethod; 28 salcianu 1.1.2.1 import harpoon.ClassFile.HCode; 29 salcianu 1.1.2.1 import harpoon.ClassFile.HClass; 30 salcianu 1.1.2.18 import harpoon.ClassFile.Linker; 31 salcianu 1.1.2.1 32 salcianu 1.5 import harpoon.IR.Quads.Code; 33 salcianu 1.1.2.1 import harpoon.IR.Quads.QuadVisitor; 34 salcianu 1.1.2.1 import harpoon.IR.Quads.Quad; 35 salcianu 1.7 import harpoon.IR.Quads.QuadNoSSA; 36 salcianu 1.7 import harpoon.IR.Quads.QuadSSA; 37 salcianu 1.7 import harpoon.IR.Quads.QuadSSI; 38 salcianu 1.1.2.1 import harpoon.IR.Quads.HEADER; 39 salcianu 1.1.2.1 import harpoon.IR.Quads.METHOD; 40 salcianu 1.1.2.1 import harpoon.IR.Quads.CALL; 41 salcianu 1.1.2.1 import harpoon.IR.Quads.MOVE; 42 salcianu 1.1.2.1 import harpoon.IR.Quads.GET; 43 salcianu 1.1.2.1 import harpoon.IR.Quads.AGET; 44 salcianu 1.1.2.1 import harpoon.IR.Quads.NEW; 45 salcianu 1.1.2.1 import harpoon.IR.Quads.ANEW; 46 salcianu 1.1.2.1 import harpoon.IR.Quads.TYPECAST; 47 salcianu 1.1.2.1 import harpoon.IR.Quads.CONST; 48 salcianu 1.5 import harpoon.IR.Quads.SIGMA; 49 salcianu 1.5 import harpoon.IR.Quads.PHI; 50 salcianu 1.5 import harpoon.IR.Quads.CJMP; 51 salcianu 1.5 import harpoon.IR.Quads.INSTANCEOF; 52 salcianu 1.7 import harpoon.IR.Quads.OPER; 53 salcianu 1.7 import harpoon.IR.Quads.CONST; 54 salcianu 1.7 import harpoon.IR.Quads.Qop; 55 salcianu 1.1.2.1 56 salcianu 1.1.2.1 import harpoon.Temp.Temp; 57 salcianu 1.1.2.1 58 salcianu 1.13 import harpoon.Util.Graphs.DiGraph; 59 salcianu 1.1.2.6 import harpoon.Util.Graphs.SCComponent; 60 salcianu 1.11 import harpoon.Util.Graphs.Navigator; 61 salcianu 1.13 import harpoon.Util.Graphs.TopSortedCompDiGraph; 62 salcianu 1.1.2.1 import harpoon.Analysis.PointerAnalysis.PAWorkList; 63 salcianu 1.1.2.23 import harpoon.Analysis.PointerAnalysis.Debug; 64 salcianu 1.1.2.1 65 salcianu 1.1.2.1 import harpoon.Util.Util; 66 salcianu 1.1.2.25 import harpoon.Util.UComp; 67 salcianu 1.1.2.1 68 salcianu 1.1.2.21 import harpoon.Util.DataStructs.Relation; 69 salcianu 1.1.2.24 import harpoon.Util.DataStructs.RelationImpl; 70 salcianu 1.1.2.21 import harpoon.Util.DataStructs.RelationEntryVisitor; 71 salcianu 1.1.2.21 72 salcianu 1.1.2.21 73 salcianu 1.1.2.1 /** 74 salcianu 1.1.2.1 * <code>MetaCallGraphImpl</code> is a full-power implementation of the 75 salcianu 1.1.2.24 <code>MetaCallGraph</code> interface. This is <i>the</i> class to use 76 salcianu 1.1.2.24 if you want to play with meta-methods.<br> 77 salcianu 1.1.2.1 78 salcianu 1.1.2.1 Otherwise, you can simply use 79 salcianu 1.1.2.1 <code>FakeCallGraph</code> which allows you to run things that need 80 salcianu 1.1.2.1 meta method representation of the program even without generating them 81 salcianu 1.1.2.1 by simply providing a meta methods-like interface for the standard 82 salcianu 1.1.2.1 <code>CallGraph</code>. 83 salcianu 1.1.2.1 * 84 cananian 1.1.2.27 * @author Alexandru SALCIANU <salcianu@retezat.lcs.mit.edu> 85 salcianu 1.15 * @version $Id: MetaCallGraphImpl.java,v 1.15 2004/03/06 21:52:21 salcianu Exp $ 86 salcianu 1.1.2.1 */ 87 salcianu 1.1.2.20 public class MetaCallGraphImpl extends MetaCallGraphAbstr { 88 salcianu 1.1.2.1 89 salcianu 1.8 public static boolean COLL_HACK = false; 90 salcianu 1.8 private static boolean DEBUG_COLL_HACK = true; 91 salcianu 1.8 92 salcianu 1.8 // true if a collection may be stored into a collection 93 salcianu 1.8 private boolean no_coll_in_coll = true; 94 salcianu 1.8 95 salcianu 1.8 // If a call might call a native, we don't try to detect all the 96 salcianu 1.8 // methods that are called there: pointer analysis would anyway 97 salcianu 1.8 // skip that call (and consider it a source of escapability) 98 salcianu 1.8 public static boolean TOUGH_ON_NATIVES = false; 99 salcianu 1.8 100 salcianu 1.1.2.1 private static boolean DEBUG = false; 101 salcianu 1.1.2.8 private static boolean DEBUG_CH = false; 102 salcianu 1.1.2.18 private static boolean COUNTER = true; 103 salcianu 1.1.2.1 104 salcianu 1.1.2.25 /** Make sure the results of the query methods (getCalles like) don't 105 salcianu 1.1.2.25 depend on the run; facilitate the debugging. */ 106 salcianu 1.1.2.25 public static final boolean DETERMINISTIC = true; 107 salcianu 1.1.2.25 108 salcianu 1.1.2.24 private static int SPEC_BOUND = 3; 109 salcianu 1.1.2.24 110 salcianu 1.1.2.1 // in "caution" mode, plenty of tests are done to protect ourselves 111 salcianu 1.1.2.1 // against errors in other components (ex: ReachingDefs) 112 salcianu 1.1.2.8 private static final boolean CAUTION = true; 113 salcianu 1.1.2.1 114 salcianu 1.1.2.28 private CachingCodeFactory hcf; 115 salcianu 1.1.2.5 private ClassHierarchy ch; 116 salcianu 1.8 private Linker linker; 117 salcianu 1.1.2.1 118 salcianu 1.1.2.24 // the set of the classes T such that a new T instruction might be executed 119 salcianu 1.1.2.24 // by the analyzed application. 120 salcianu 1.1.2.24 private Set instantiated_classes = null; 121 salcianu 1.1.2.24 122 salcianu 1.7 // indicates whether we use the SSA / SSI format 123 salcianu 1.7 private boolean ssx_form = false; 124 salcianu 1.7 125 salcianu 1.8 // Any method can throw an exception that is subclass of these 126 salcianu 1.8 // two classes (without explicitly declaring it). 127 salcianu 1.8 private HClass jl_RuntimeException; 128 salcianu 1.8 private HClass jl_Error; 129 salcianu 1.8 private HClass jl_Thread; 130 salcianu 1.8 private HClass jl_Runnable; 131 salcianu 1.8 private HClass jl_Object; 132 salcianu 1.8 private HMethod hm_HashtablePut; 133 salcianu 1.8 134 salcianu 1.1.2.1 /** Creates a <code>MetaCallGraphImpl</code>. It must receive, in its 135 salcianu 1.1.2.4 last parameter, the <code>main</code> method of the program. */ 136 salcianu 1.8 public MetaCallGraphImpl(CachingCodeFactory hcf, Linker linker, 137 salcianu 1.8 ClassHierarchy ch, Set hmroots) { 138 salcianu 1.5 139 salcianu 1.5 assert 140 salcianu 1.7 hcf.getCodeName().equals(QuadNoSSA.codename) || 141 salcianu 1.7 hcf.getCodeName().equals(QuadSSA.codename) || 142 salcianu 1.7 hcf.getCodeName().equals(QuadSSI.codename) : 143 salcianu 1.5 "Cannot work with " + hcf.getCodeName(); 144 salcianu 1.5 145 salcianu 1.7 ssx_form = 146 salcianu 1.7 hcf.getCodeName().equals(QuadSSA.codename) || 147 salcianu 1.7 hcf.getCodeName().equals(QuadSSI.codename); 148 salcianu 1.7 149 salcianu 1.5 System.out.println("MetaCallGraphImpl started with " + 150 salcianu 1.8 hcf.getCodeName() + " ssx = " + ssx_form + 151 salcianu 1.8 (COLL_HACK ? "COLL_HACK" : "")); 152 salcianu 1.5 153 salcianu 1.1.2.28 this.hcf = hcf; 154 salcianu 1.1.2.28 this.ch = ch; 155 salcianu 1.8 this.linker = linker; 156 salcianu 1.8 init_class_handlers(); 157 salcianu 1.8 158 salcianu 1.8 build_meta_call_graph(hmroots); 159 salcianu 1.8 // convert the big format (Set oriented) into the compact one (arrays) 160 salcianu 1.8 compact(); 161 salcianu 1.8 // clean up temporary data to free up some space 162 salcianu 1.8 cleanup_temp_data(); 163 salcianu 1.8 } 164 salcianu 1.8 165 salcianu 1.8 166 salcianu 1.8 private void build_meta_call_graph(Set hmroots) { 167 salcianu 1.8 compute_instantiated_classes(); 168 salcianu 1.8 169 salcianu 1.8 if(COLL_HACK) 170 salcianu 1.8 init_coll_hack(); 171 salcianu 1.8 172 salcianu 1.8 if(COUNTER) 173 salcianu 1.8 System.out.println(); 174 salcianu 1.8 175 salcianu 1.8 // analyze all the roots 176 salcianu 1.8 for(Iterator it = hmroots.iterator(); it.hasNext(); ) 177 salcianu 1.8 analyze(new MetaMethod((HMethod) it.next(), true)); 178 salcianu 1.8 179 salcianu 1.8 if(COLL_HACK) { 180 salcianu 1.8 // remove some unrealizable edges from the call graph 181 salcianu 1.8 trim_call_graph(); 182 salcianu 1.8 // print some debug info 183 salcianu 1.8 if(DEBUG_COLL_HACK) 184 salcianu 1.8 print_coll_hack_debug(); 185 salcianu 1.8 } 186 salcianu 1.8 } 187 salcianu 1.8 188 salcianu 1.8 189 salcianu 1.8 private void cleanup_temp_data() { 190 salcianu 1.8 // activate the GC 191 salcianu 1.8 callees1 = null; 192 salcianu 1.8 callees2 = null; 193 salcianu 1.8 this.ch = null; 194 salcianu 1.8 this.hcf = null; 195 salcianu 1.8 cleanup_class_handlers(); 196 salcianu 1.8 197 salcianu 1.8 ets2et = null; 198 salcianu 1.8 mh2md = null; 199 salcianu 1.8 param_types = null; 200 salcianu 1.8 201 salcianu 1.8 // null these out so that we can serialize the object [CSA] 202 salcianu 1.8 // (alternatively, could mark all of these as 'transient') 203 salcianu 1.8 qvis_dd = null; 204 salcianu 1.8 qvis_ti = null; 205 salcianu 1.8 ets2et = null; 206 salcianu 1.8 ets_test = null; 207 salcianu 1.8 implementers = null; 208 salcianu 1.8 kids = null; 209 salcianu 1.8 instantiated_classes = null; 210 salcianu 1.8 211 salcianu 1.8 if(COLL_HACK) 212 salcianu 1.8 cleanup_coll_hack(); 213 salcianu 1.8 214 salcianu 1.8 // okay, now garbage-collect. 215 salcianu 1.8 System.gc(); 216 salcianu 1.8 } 217 salcianu 1.8 218 salcianu 1.8 219 salcianu 1.8 private void init_class_handlers() { 220 salcianu 1.8 jl_Thread = linker.forName("java.lang.Thread"); 221 salcianu 1.8 jl_Runnable = linker.forName("java.lang.Runnable"); 222 salcianu 1.8 jl_RuntimeException = linker.forName("java.lang.RuntimeException"); 223 salcianu 1.8 jl_Error = linker.forName("java.lang.Error"); 224 salcianu 1.8 } 225 salcianu 1.8 226 salcianu 1.8 private void cleanup_class_handlers() { 227 salcianu 1.8 jl_Thread = null; 228 salcianu 1.8 jl_Runnable = null; 229 salcianu 1.8 jl_RuntimeException = null; 230 salcianu 1.8 jl_Error = null; 231 salcianu 1.8 } 232 salcianu 1.8 233 salcianu 1.1.2.9 234 salcianu 1.8 private void compute_instantiated_classes() { 235 salcianu 1.1.2.24 // HACK: Normally, the call graph and the set instantiated_classes 236 salcianu 1.1.2.24 // should be computed simultaneously; we use the ClassHierarchy 237 salcianu 1.1.2.24 // to get the latter. 238 salcianu 1.5 // For any type T such that a "new T" might be executed, there is at 239 salcianu 1.1.2.24 // least one method of T executed. So, we can approximate the set 240 salcianu 1.1.2.24 // of actually instantiated classes by looking at the declaring 241 salcianu 1.1.2.24 // class of all callable methods. 242 salcianu 1.1.2.24 instantiated_classes = new HashSet(); 243 salcianu 1.1.2.24 Set old_ic = ch.instantiatedClasses(); 244 cananian 1.12 for(Object hmO : ch.callableMethods()) { 245 cananian 1.12 HMethod hm = (HMethod) hmO; 246 salcianu 1.1.2.24 if(Modifier.isStatic(hm.getModifiers())) continue; 247 salcianu 1.1.2.24 HClass hclass = hm.getDeclaringClass(); 248 salcianu 1.1.2.24 if(Modifier.isAbstract(hclass.getModifiers())) continue; 249 salcianu 1.1.2.24 if(old_ic.contains(hclass)) 250 salcianu 1.1.2.24 instantiated_classes.add(hclass); 251 salcianu 1.1.2.24 } 252 salcianu 1.1.2.24 // however, there is an exception: the arrays (they are objects too) 253 cananian 1.12 for(Object hclassO : ch.instantiatedClasses()) { 254 cananian 1.12 HClass hclass = (HClass) hclassO; 255 salcianu 1.1.2.24 if(hclass.isArray()) 256 salcianu 1.1.2.24 instantiated_classes.add(hclass); 257 salcianu 1.1.2.24 } 258 salcianu 1.1.2.24 259 salcianu 1.1.2.24 if(DEBUG_CH) { 260 salcianu 1.1.2.24 Set cls = instantiated_classes; 261 salcianu 1.1.2.24 System.out.println("INSTANTIATED CLASS(ES) (" + 262 salcianu 1.1.2.24 cls.size() + ") : {"); 263 salcianu 1.1.2.24 for(Iterator it = cls.iterator(); it.hasNext(); ) 264 salcianu 1.1.2.24 System.out.println(" " + ((HClass) it.next())); 265 salcianu 1.1.2.24 System.out.println("}"); 266 salcianu 1.1.2.24 } 267 salcianu 1.8 } 268 salcianu 1.1.2.24 269 salcianu 1.1.2.1 270 salcianu 1.1.2.1 // Converts the big format (Set oriented) into the compact one (arrays) 271 salcianu 1.1.2.1 // Takes the data from callees1(2) and puts it into callees1(2)_cmpct 272 salcianu 1.8 private void compact() { 273 cananian 1.12 for(Object mmO : callees1.keys()) { 274 cananian 1.12 MetaMethod mm = (MetaMethod) mmO; 275 salcianu 1.1.2.21 Set callees = callees1.getValues(mm); 276 salcianu 1.1.2.1 MetaMethod[] mms = 277 salcianu 1.1.2.1 (MetaMethod[]) callees.toArray(new MetaMethod[callees.size()]); 278 salcianu 1.1.2.25 if(DETERMINISTIC) 279 salcianu 1.1.2.25 Arrays.sort(mms, UComp.uc); 280 salcianu 1.1.2.25 callees1_cmpct.put(mm, mms); 281 salcianu 1.1.2.1 } 282 salcianu 1.1.2.1 283 cananian 1.12 for(Object mmO : callees2.keySet()) { 284 cananian 1.12 MetaMethod mm = (MetaMethod) mmO; 285 salcianu 1.1.2.1 Relation rel = (Relation) callees2.get(mm); 286 salcianu 1.1.2.1 Map map_cmpct = (Map) callees2_cmpct.get(mm); 287 salcianu 1.1.2.1 if(map_cmpct == null) 288 salcianu 1.1.2.1 callees2_cmpct.put(mm,map_cmpct = new HashMap()); 289 cananian 1.12 for(Object csO : rel.keys()){ 290 cananian 1.12 CALL cs = (CALL) csO; 291 salcianu 1.1.2.1 // cees is the set of callees in "mm" at call site "cs". 292 salcianu 1.1.2.21 Set cees = rel.getValues(cs); 293 salcianu 1.1.2.1 MetaMethod[] mms = 294 salcianu 1.1.2.1 (MetaMethod[]) cees.toArray(new MetaMethod[cees.size()]); 295 salcianu 1.1.2.25 if(DETERMINISTIC) 296 salcianu 1.1.2.25 Arrays.sort(mms, UComp.uc); 297 salcianu 1.1.2.25 map_cmpct.put(cs, mms); 298 salcianu 1.1.2.1 } 299 salcianu 1.1.2.1 } 300 salcianu 1.1.2.1 } 301 salcianu 1.1.2.1 302 salcianu 1.1.2.1 // Relation<MetaMethod, MetaMethod> stores the association between 303 salcianu 1.1.2.1 // the caller and its callees 304 salcianu 1.1.2.24 private Relation callees1 = new RelationImpl(); 305 salcianu 1.1.2.1 306 salcianu 1.1.2.1 // Map<MetaMethod,Relation<CALL,MetaMethod>> stores the association 307 salcianu 1.1.2.1 // between the caller and its calees at a specific call site 308 salcianu 1.1.2.1 private Map callees2 = new HashMap(); 309 salcianu 1.1.2.1 310 salcianu 1.1.2.9 // Build up the meta call graph, starting from a "root" method. 311 salcianu 1.1.2.9 // The classic example of a root method is "main", but there could 312 salcianu 1.1.2.9 // be others called by the JVM before main. 313 salcianu 1.8 private void analyze(HMethod root) { 314 salcianu 1.8 if(COLL_HACK && root.equals(hm_HashtablePut)) { 315 salcianu 1.8 if(DEBUG_COLL_HACK) 316 salcianu 1.8 System.out.println("COLL_HACK: treat Hashtable.put: " + 317 salcianu 1.8 "java.util.Properties x String x String"); 318 salcianu 1.8 319 salcianu 1.8 GenType hashmap_gt = 320 salcianu 1.8 new GenType(linker.forName("java.util.Properties"), 321 salcianu 1.8 GenType.MONO); 322 salcianu 1.8 GenType key_gt = 323 salcianu 1.8 new GenType(linker.forName("java.lang.String"), GenType.POLY); 324 salcianu 1.8 GenType value_gt = key_gt; 325 salcianu 1.8 GenType[] gts = new GenType[]{hashmap_gt, key_gt, value_gt}; 326 salcianu 1.8 analyze(new MetaMethod(root, gts)); 327 salcianu 1.8 328 salcianu 1.8 return; 329 salcianu 1.8 } 330 salcianu 1.8 331 salcianu 1.1.2.9 // we are extremely conservative: a root method could be called 332 salcianu 1.1.2.9 // with any subtypes for its arguments, so we treat it as a 333 salcianu 1.1.2.9 // polymorphic one. 334 salcianu 1.8 analyze(new MetaMethod(root, true)); 335 salcianu 1.1.2.1 } 336 salcianu 1.1.2.1 337 salcianu 1.8 338 salcianu 1.1.2.1 private PAWorkList WMM = null; 339 salcianu 1.1.2.1 private Set analyzed_mm = null; 340 salcianu 1.1.2.1 private MetaMethod mm_work = null; 341 salcianu 1.1.2.1 342 salcianu 1.1.2.9 private int mm_count = 0; 343 salcianu 1.1.2.9 344 salcianu 1.1.2.1 private void analyze(MetaMethod root_mm){ 345 salcianu 1.1.2.9 if(COUNTER) 346 salcianu 1.1.2.26 System.out.print(root_mm + " "); 347 salcianu 1.1.2.9 348 salcianu 1.1.2.1 analyzed_mm = new HashSet(); 349 salcianu 1.1.2.1 WMM = new PAWorkList(); 350 salcianu 1.1.2.1 WMM.add(root_mm); 351 salcianu 1.1.2.1 while(!WMM.isEmpty()){ 352 salcianu 1.1.2.1 mm_work = (MetaMethod) WMM.remove(); 353 salcianu 1.1.2.9 354 salcianu 1.8 /* 355 salcianu 1.8 if(COLL_HACK == true) 356 salcianu 1.8 coll_hack_examine_method(mm_work); 357 salcianu 1.8 */ 358 salcianu 1.8 359 salcianu 1.5 if(COUNTER) { 360 salcianu 1.1.2.9 mm_count++; 361 salcianu 1.1.2.26 if(mm_count % 10 == 0) 362 salcianu 1.1.2.26 System.out.print("."); 363 salcianu 1.1.2.9 } 364 salcianu 1.1.2.9 365 salcianu 1.1.2.1 analyzed_mm.add(mm_work); 366 salcianu 1.1.2.1 analyze_meta_method(); 367 salcianu 1.1.2.1 } 368 salcianu 1.5 369 salcianu 1.1.2.1 all_meta_methods.addAll(analyzed_mm); 370 salcianu 1.1.2.9 371 salcianu 1.8 // enable some GC! 372 salcianu 1.8 analyzed_mm = null; 373 salcianu 1.8 WMM = null; 374 salcianu 1.8 mm_work = null; 375 salcianu 1.8 376 salcianu 1.1.2.9 if(COUNTER) 377 salcianu 1.1.2.26 System.out.println(" " + mm_count + " analyzed meta-method(s)"); 378 salcianu 1.1.2.1 } 379 salcianu 1.1.2.1 380 salcianu 1.5 private Collection calls = null; 381 salcianu 1.1.2.1 382 salcianu 1.1.2.24 private void analyze_meta_method() { 383 salcianu 1.9 if(DEBUG) 384 salcianu 1.1.2.24 System.out.println("\n\n%%: " + mm_work); 385 salcianu 1.1.2.1 386 salcianu 1.1.2.1 HMethod hm = mm_work.getHMethod(); 387 salcianu 1.1.2.1 388 salcianu 1.1.2.1 // native method, no code for analysis -> return immediately 389 salcianu 1.1.2.1 if(Modifier.isNative(hm.getModifiers())) return; 390 salcianu 1.1.2.1 391 salcianu 1.1.2.24 MethodData md = get_method_data(hm); 392 salcianu 1.1.2.24 ets2et = md.ets2et; 393 salcianu 1.1.2.24 calls = md.calls; 394 salcianu 1.1.2.1 395 salcianu 1.7 if(DEBUG) 396 salcianu 1.7 display_mm_data(mm_work); 397 salcianu 1.1.2.1 398 salcianu 1.5 set_parameter_types(mm_work, hcf.convert(hm)); 399 salcianu 1.1.2.1 400 salcianu 1.13 compute_types(md.sccs); 401 salcianu 1.1.2.1 analyze_calls(); 402 salcianu 1.1.2.1 403 salcianu 1.1.2.3 // before quiting this meta-method, remove the types we computed 404 salcianu 1.1.2.3 // for the ExactTemps. The component graph of ExactTemps (and so, 405 salcianu 1.1.2.24 // the ExactTemps themselves) is specific to an HMethod and so, 406 salcianu 1.1.2.3 // they can be shared by many meta-methods derived from the same 407 salcianu 1.1.2.3 // HMethod. Of course, I don't want the next analyzed meta-method 408 salcianu 1.1.2.3 // to use the types computed for this one. 409 salcianu 1.15 for(SCComponent scc : md.sccs) 410 salcianu 1.15 for(Object ets0 : scc.nodes()) 411 salcianu 1.15 ((ExactTemp) ets0).clearTypeSet(); 412 salcianu 1.1.2.1 } 413 salcianu 1.1.2.1 414 salcianu 1.1.2.1 415 salcianu 1.1.2.1 // after the types of all the interesting ExactTemps are known, 416 salcianu 1.1.2.1 // examine each call site from this metamethod and build the 417 salcianu 1.1.2.1 // meta-call-graph. 418 salcianu 1.1.2.1 private void analyze_calls(){ 419 salcianu 1.1.2.1 for(Iterator it_calls = calls.iterator();it_calls.hasNext();) 420 salcianu 1.1.2.1 analyze_one_call((CALL) it_calls.next()); 421 salcianu 1.1.2.1 } 422 salcianu 1.1.2.1 423 salcianu 1.1.2.1 ////// "analyze_one_call" related stuff BEGIN ========== 424 salcianu 1.1.2.1 425 salcianu 1.1.2.1 // Records the fact that mcaller could call mcallee at the call site cs. 426 salcianu 1.1.2.1 private void record_call(MetaMethod mcaller, CALL cs, MetaMethod mcallee){ 427 salcianu 1.1.2.1 callees1.add(mcaller,mcallee); 428 salcianu 1.1.2.1 Relation rel = (Relation) callees2.get(mcaller); 429 salcianu 1.1.2.1 if(rel == null) 430 salcianu 1.1.2.24 callees2.put(mcaller,rel = new RelationImpl()); 431 salcianu 1.1.2.1 rel.add(cs,mcallee); 432 salcianu 1.1.2.1 } 433 salcianu 1.1.2.1 434 salcianu 1.1.2.1 // the specialized types will be stored here. 435 salcianu 1.1.2.1 private GenType[] param_types = null; 436 salcianu 1.1.2.1 437 salcianu 1.1.2.1 // counts the number of metamethods called at a "virtual" call site. 438 salcianu 1.1.2.1 private int nb_meta_methods; 439 salcianu 1.1.2.1 440 salcianu 1.1.2.1 // determine the exact meta-method which is called at the call site "cs", 441 salcianu 1.1.2.1 // based on the specialized types found in "param_types". 442 salcianu 1.5 private void specialize_the_call(HMethod hm, CALL cs) { 443 salcianu 1.5 if(DEBUG) { 444 salcianu 1.5 System.out.println("hm = " + hm); 445 salcianu 1.5 System.out.println("cs = " + cs); 446 salcianu 1.5 System.out.print("param_types = [ "); 447 salcianu 1.5 for(int i = 0; i < param_types.length ; i++) 448 salcianu 1.5 System.out.print(param_types[i] + " "); 449 salcianu 1.5 System.out.println("]"); 450 salcianu 1.5 } 451 salcianu 1.8 452 salcianu 1.8 if(COLL_HACK) 453 salcianu 1.8 coll_hack_fix_params(hm, cs); 454 salcianu 1.8 455 salcianu 1.8 MetaMethod mm_callee = new MetaMethod(hm, param_types); 456 salcianu 1.5 nb_meta_methods++; 457 salcianu 1.5 record_call(mm_work, cs, mm_callee); 458 salcianu 1.8 if(!analyzed_mm.contains(mm_callee)) { 459 salcianu 1.8 460 salcianu 1.8 // TODO: MOVE it TO THE WMM loop 461 salcianu 1.8 if(COLL_HACK == true) 462 salcianu 1.8 coll_hack_examine_method(mm_callee); 463 salcianu 1.8 464 salcianu 1.5 WMM.add(mm_callee); 465 salcianu 1.8 } 466 salcianu 1.8 } 467 salcianu 1.8 468 salcianu 1.8 469 salcianu 1.8 // COLL_HACK methods BEGIN 470 salcianu 1.8 471 salcianu 1.8 // HashSet is implemented as a HashMap where all values are equal 472 salcianu 1.8 // to a preallocated Object. Therefore, when Map.put is called 473 salcianu 1.8 // from HashSet, the second parameter is not any Object, but 474 salcianu 1.8 // exactly Object. If we were able to infere the concrete types 475 salcianu 1.8 // stored in object fields, this hack wouldn't be necessary :) 476 salcianu 1.8 // TODO: implement a real analysis for field concrete types 477 salcianu 1.8 private void coll_hack_fix_params(HMethod hm, CALL cs) { 478 salcianu 1.8 HMethod caller = mm_work.getHMethod(); 479 salcianu 1.8 480 salcianu 1.8 assert hm != null; 481 salcianu 1.8 assert caller != null; 482 salcianu 1.8 assert jl_Map != null; 483 salcianu 1.8 assert jl_Object != null; 484 salcianu 1.8 485 salcianu 1.8 if(caller.getDeclaringClass().equals(ju_HashSet) && 486 salcianu 1.8 hm.getName().equals("put") && 487 salcianu 1.8 jl_Map.isSuperinterfaceOf(hm.getDeclaringClass())) 488 salcianu 1.8 param_types[2] = new GenType(jl_Object, GenType.MONO); 489 salcianu 1.1.2.1 } 490 salcianu 1.1.2.1 491 salcianu 1.8 492 salcianu 1.8 private void coll_hack_examine_method(MetaMethod mm) { 493 salcianu 1.8 if(// Collection.add(ELEMENT); 494 salcianu 1.8 test_coll(mm, "java.util.Collection", "add", 1, 1) || 495 salcianu 1.8 // Map.put(KEY, value); 496 salcianu 1.8 test_coll(mm, "java.util.Map", "put", 2, 1) || 497 salcianu 1.8 // Map.put(key, VALUE); 498 salcianu 1.8 test_coll(mm, "java.util.Map", "put", 2, 2) || 499 salcianu 1.8 // List.add(index, ELEMENT); 500 salcianu 1.8 test_coll(mm, "java.util.List", "add", 2, 2) || 501 salcianu 1.8 // Vector.addElement(ELEMENT); 502 salcianu 1.8 test_coll(mm, "java.util.Vector", "addElement", 1, 1) || 503 salcianu 1.8 // Vector.copyInto(ELEMENT[]); 504 salcianu 1.8 test_coll2(mm, "java.util.Vector", "copyInto", 1, 1)) { 505 salcianu 1.8 // you can put some debug message here 506 salcianu 1.8 } 507 salcianu 1.8 } 508 salcianu 1.8 509 salcianu 1.8 private boolean test_coll2(MetaMethod mm, String cls, String mthd, 510 salcianu 1.8 int arity, int index) { 511 salcianu 1.8 512 salcianu 1.8 if(!is_this_method(mm, cls, mthd, arity)) 513 salcianu 1.8 return false; 514 salcianu 1.8 515 salcianu 1.8 GenType gt = mm.getType(index); 516 salcianu 1.8 HClass hclass = gt.getHClass(); 517 salcianu 1.8 518 salcianu 1.8 assert hclass.getComponentType() == null : 519 salcianu 1.8 "mm.getType(index) is expected to be an array: " + mm; 520 salcianu 1.8 521 salcianu 1.8 Set els = 522 salcianu 1.8 get_instantiated_children(new GenType(hclass, GenType.POLY)); 523 salcianu 1.8 put_in_colls.addAll(els); 524 salcianu 1.8 525 salcianu 1.8 if(mthd.equals("put")) 526 salcianu 1.8 if(index == 1) keys_put_in_maps.addAll(els); 527 salcianu 1.8 else if(index == 2) values_put_in_maps.addAll(els); 528 salcianu 1.8 else assert false : "unexpected index " + index; 529 salcianu 1.8 530 salcianu 1.8 return 531 salcianu 1.8 intersect(els, inst_colls); 532 salcianu 1.8 } 533 salcianu 1.8 534 salcianu 1.8 535 salcianu 1.8 // Checks whether mm corresponds to a method called "mthd" from a 536 salcianu 1.8 // subclass of "cls" and having "arity" arguments. 537 salcianu 1.8 private boolean is_this_method(MetaMethod mm, String cls, String mthd, 538 salcianu 1.8 int arity) { 539 salcianu 1.8 HMethod hm = mm.getHMethod(); 540 salcianu 1.8 541 salcianu 1.8 if(hm.isStatic() || 542 salcianu 1.8 !hm.getName().equals(mthd) || 543 salcianu 1.8 (hm.getParameterNames().length != arity)) return false; 544 salcianu 1.8 545 salcianu 1.8 // name2colls stores the most popular classes 546 salcianu 1.8 HClass hcoll = (HClass) name2coll.get(cls); 547 salcianu 1.8 548 salcianu 1.8 if(hcoll == null) 549 salcianu 1.8 hcoll = linker.forName(cls); 550 salcianu 1.8 551 salcianu 1.8 return 552 salcianu 1.8 ((hcoll.isInterface() && 553 salcianu 1.8 hcoll.isSuperinterfaceOf(hm.getDeclaringClass())) 554 salcianu 1.8 || 555 salcianu 1.8 (!hcoll.isInterface() && 556 salcianu 1.8 hcoll.isSuperclassOf(hm.getDeclaringClass()))); 557 salcianu 1.8 } 558 salcianu 1.8 559 salcianu 1.8 560 salcianu 1.8 // Checks whether mm is a method of a subclass of "cls", has name 561 salcianu 1.8 // "mthd", arity "arity" and param_types[index] might be a 562 salcianu 1.8 // collection (ie, it implements java.util.Collection or 563 salcianu 1.8 // java.util.Map). 564 salcianu 1.8 // 565 salcianu 1.8 // Also the type of the argument is stored in the appropriate set: 566 salcianu 1.8 // hash keys, hash values and / or collection elements. 567 salcianu 1.8 // 568 salcianu 1.8 // Note: We start counting parameters from 1 (0 is this). 569 salcianu 1.8 private boolean test_coll(MetaMethod mm, String cls, String mthd, 570 salcianu 1.8 int arity, int index) { 571 salcianu 1.8 if(!is_this_method(mm, cls, mthd, arity)) 572 salcianu 1.8 return false; 573 salcianu 1.8 574 salcianu 1.8 GenType gt = mm.getType(index); 575 salcianu 1.8 576 salcianu 1.8 System.out.println 577 salcianu 1.8 ("test_coll:\n\t mm = " + mm + "\n\t gt = " + gt); 578 salcianu 1.8 579 salcianu 1.8 Set els = get_instantiated_children(gt); 580 salcianu 1.8 if(put_in_colls.addAll(els)) { 581 salcianu 1.8 System.out.println 582 salcianu 1.8 ("COLL_HACK: new put_in_colls:" + 583 salcianu 1.8 "\n caller = " + mm_work + 584 salcianu 1.8 "\n callee = " + mm + 585 salcianu 1.8 "\n index = " + index + 586 salcianu 1.8 "\n els = " + els); 587 salcianu 1.8 } 588 salcianu 1.8 589 salcianu 1.8 if(mthd.equals("put")) 590 salcianu 1.8 if(index == 1) keys_put_in_maps.addAll(els); 591 salcianu 1.8 else if(index == 2) values_put_in_maps.addAll(els); 592 salcianu 1.8 else assert false : "unexpected index " + index; 593 salcianu 1.8 594 salcianu 1.8 return 595 salcianu 1.8 intersect(els, inst_colls); 596 salcianu 1.8 } 597 salcianu 1.8 598 salcianu 1.8 // auxiliary data for COLL_HACK 599 salcianu 1.8 private static Map name2coll = null; 600 salcianu 1.8 // instr_collections = inst_colls + inst_maps 601 salcianu 1.8 private static Set inst_colls = null; 602 salcianu 1.8 // Set of types put into collections: maps, sets, lists etc. 603 salcianu 1.8 private Set put_in_colls; 604 salcianu 1.8 // Set of types used as keys in maps 605 salcianu 1.8 private Set keys_put_in_maps; 606 salcianu 1.8 // Set of types used as values in maps 607 salcianu 1.8 private Set values_put_in_maps; 608 salcianu 1.8 609 salcianu 1.8 610 salcianu 1.8 // initialize data structs used by COLL_HACK activated code 611 salcianu 1.8 private void init_coll_hack() { 612 salcianu 1.8 613 salcianu 1.8 jl_Object = linker.forName("java.lang.Object"); 614 salcianu 1.8 ju_HashSet = linker.forName("java.util.HashSet"); 615 salcianu 1.8 616 salcianu 1.8 hm_HashtablePut = 617 salcianu 1.8 linker.forName("java.util.Hashtable"). 618 salcianu 1.8 getMethod("put", new HClass[] {jl_Object, jl_Object}); 619 salcianu 1.8 620 salcianu 1.8 assert hm_HashtablePut != null; 621 salcianu 1.8 622 salcianu 1.8 name2coll = new HashMap(); 623 salcianu 1.8 inst_colls = new HashSet(); 624 salcianu 1.8 for(int i = 0; i < relv_colls.length; i++) { 625 salcianu 1.8 HClass hclass = linker.forName(relv_colls[i]); 626 salcianu 1.8 inst_colls.addAll(get_instantiated_children(hclass)); 627 salcianu 1.8 name2coll.put(relv_colls[i], hclass); 628 salcianu 1.8 } 629 salcianu 1.8 put_in_colls = new HashSet(); 630 salcianu 1.8 keys_put_in_maps = new HashSet(); 631 salcianu 1.8 values_put_in_maps = new HashSet(); 632 salcianu 1.8 633 salcianu 1.8 jl_Collection = (HClass) name2coll.get("java.util.Collection"); 634 salcianu 1.8 jl_Map = (HClass) name2coll.get("java.util.Map"); 635 salcianu 1.8 636 salcianu 1.8 if(DEBUG_COLL_HACK) 637 salcianu 1.8 Util.print_collection(inst_colls, "Inst. collections"); 638 salcianu 1.8 639 cananian 1.12 for(Object collO : inst_colls) { 640 cananian 1.12 HClass coll = (HClass) collO; 641 salcianu 1.8 if(!"java.util".equals(coll.getPackage())) { 642 salcianu 1.8 System.out.println 643 salcianu 1.8 ("COLL_HACK: Non java.util collections created: " + 644 salcianu 1.8 coll + "\n\t=> COLL_HACK turned off!"); 645 salcianu 1.8 COLL_HACK = false; 646 salcianu 1.8 } 647 salcianu 1.8 } 648 salcianu 1.8 } 649 salcianu 1.8 private static String[] relv_colls = { 650 salcianu 1.8 "java.util.Collection", "java.util.Map", 651 salcianu 1.8 "java.util.List", "java.util.Vector" 652 salcianu 1.8 }; 653 salcianu 1.8 654 salcianu 1.8 private HClass jl_Collection; 655 salcianu 1.8 private HClass jl_Map; 656 salcianu 1.8 private HClass ju_HashSet; 657 salcianu 1.8 658 salcianu 1.8 private void cleanup_coll_hack() { 659 salcianu 1.8 name2coll = null; 660 salcianu 1.8 inst_colls = null; 661 salcianu 1.8 put_in_colls = null; 662 salcianu 1.8 keys_put_in_maps = null; 663 salcianu 1.8 values_put_in_maps = null; 664 salcianu 1.8 jl_Object = null; 665 salcianu 1.8 ju_HashSet = null; 666 salcianu 1.8 hm_HashtablePut = null; 667 salcianu 1.8 jl_Collection = null; 668 salcianu 1.8 jl_Map = null; 669 salcianu 1.8 map_upcalls = null; 670 salcianu 1.8 coll_upcalls = null; 671 salcianu 1.8 } 672 salcianu 1.8 673 salcianu 1.8 // checks whether set1 and set2 have a common element 674 salcianu 1.8 private boolean intersect(Set set1, Set set2) { 675 salcianu 1.8 for(Iterator it = set1.iterator(); it.hasNext(); ) 676 salcianu 1.8 if(set2.contains(it.next())) 677 salcianu 1.8 return true; 678 salcianu 1.8 return false; 679 salcianu 1.8 } 680 salcianu 1.8 681 salcianu 1.8 682 salcianu 1.8 private void trim_call_graph() { 683 salcianu 1.8 if(DEBUG_COLL_HACK) 684 salcianu 1.8 System.out.println("\nCOLL_HACK: trim_call_graph"); 685 salcianu 1.8 686 salcianu 1.8 init_upcalls_sets(); 687 salcianu 1.8 688 cananian 1.12 for(Object mmO : all_meta_methods) { 689 cananian 1.12 MetaMethod mm = (MetaMethod) mmO; 690 salcianu 1.8 Set upcalls = allowed_upcalls_methods(mm.getHMethod()); 691 salcianu 1.8 // upcalls == nulls means mm is not a collection method 692 salcianu 1.8 // any upcalls are possible 693 salcianu 1.8 if(upcalls == null) 694 salcianu 1.8 continue; 695 salcianu 1.8 696 salcianu 1.8 trim_callees(mm, upcalls); 697 salcianu 1.8 } 698 salcianu 1.8 } 699 salcianu 1.8 700 salcianu 1.8 private void trim_callees(MetaMethod mm, Set upcalls) { 701 salcianu 1.8 if(!callees2.containsKey(mm)) 702 salcianu 1.8 return; 703 salcianu 1.8 704 salcianu 1.8 Relation rel = (Relation) callees2.get(mm); 705 salcianu 1.8 Set calls = new HashSet(rel.keys()); 706 cananian 1.12 for(Object csO : calls) { 707 cananian 1.12 CALL cs = (CALL) csO; 708 salcianu 1.8 // non-virtual call sites cannot be trimmed 709 salcianu 1.8 if(!cs.isVirtual()) 710 salcianu 1.8 continue; 711 salcianu 1.8 Set to_remove = new HashSet(); 712 cananian 1.12 for(Object mm_calleeO : rel.getValues(cs)) { 713 cananian 1.12 MetaMethod mm_callee = (MetaMethod) mm_calleeO; 714 salcianu 1.8 HMethod hm_callee = mm_callee.getHMethod(); 715 salcianu 1.8 if((hm_callee.getName().equals("equals") || 716 salcianu 1.8 hm_callee.getName().equals("hashCode")) && 717 salcianu 1.8 !upcalls.contains(hm_callee)) 718 salcianu 1.8 to_remove.add(mm_callee); 719 salcianu 1.8 } 720 salcianu 1.8 rel.removeAll(cs, to_remove); 721 salcianu 1.8 } 722 salcianu 1.8 723 salcianu 1.8 // computes in callees the set of all mm's callees 724 salcianu 1.8 Set callees = new HashSet(); 725 cananian 1.12 for(Object csO : calls) { 726 cananian 1.12 CALL cs = (CALL) csO; 727 salcianu 1.8 callees.addAll(rel.getValues(cs)); 728 salcianu 1.8 } 729 salcianu 1.8 730 salcianu 1.8 // update callees1 731 salcianu 1.8 callees1.removeKey(mm); // 1. remove all old methods 732 salcianu 1.8 callees1.addAll(mm, callees); // 2. add new ones (fewer) 733 salcianu 1.8 } 734 salcianu 1.8 735 salcianu 1.8 736 salcianu 1.8 // "equals" & "hashCode" methods that may NOT be called from 737 salcianu 1.8 // collections = complement of equals/hashCode methods of classes 738 salcianu 1.8 // from put_in_colls 739 salcianu 1.8 private Set coll_upcalls; 740 salcianu 1.8 // "equals" & "hashCode" methods that may NOT be called from maps 741 salcianu 1.8 // = complement of equals/hashCode methods of classes from 742 salcianu 1.8 // keys/values_put_in_maps 743 salcianu 1.8 private Set map_upcalls; 744 salcianu 1.8 745 salcianu 1.8 // initialize the sets collection_upcalls and map_upcalls 746 salcianu 1.8 private void init_upcalls_sets() { 747 salcianu 1.8 HClass[] empty_args = new HClass[0]; 748 salcianu 1.8 HClass[] one_obj = new HClass[]{jl_Object}; 749 salcianu 1.8 750 salcianu 1.8 coll_upcalls = new HashSet(); 751 salcianu 1.8 map_upcalls = new HashSet(); 752 salcianu 1.8 753 cananian 1.12 for(Object hclassO : instantiated_classes) { 754 cananian 1.12 HClass hclass = (HClass) hclassO; 755 salcianu 1.8 if(put_in_colls.contains(hclass)) { 756 salcianu 1.8 coll_upcalls.add(hclass.getMethod("equals", one_obj)); 757 salcianu 1.8 coll_upcalls.add(hclass.getMethod("hashCode", empty_args)); 758 salcianu 1.8 } 759 salcianu 1.8 } 760 salcianu 1.8 761 cananian 1.12 for(Object hclassO : instantiated_classes) { 762 cananian 1.12 HClass hclass = (HClass) hclassO; 763 salcianu 1.8 if(keys_put_in_maps.contains(hclass) || 764 salcianu 1.8 values_put_in_maps.contains(hclass)) { 765 salcianu 1.8 map_upcalls.add(hclass.getMethod("equals", one_obj)); 766 salcianu 1.8 map_upcalls.add(hclass.getMethod("hashCode", empty_args)); 767 salcianu 1.8 } 768 salcianu 1.8 } 769 salcianu 1.8 770 salcianu 1.8 if(DEBUG_COLL_HACK) { 771 salcianu 1.8 Util.print_collection(coll_upcalls, "coll_upcalls"); 772 salcianu 1.8 Util.print_collection(map_upcalls, "map_upcalls"); 773 salcianu 1.8 } 774 salcianu 1.8 } 775 salcianu 1.8 776 salcianu 1.8 // returns the set of methods that cannot be called from hm 777 salcianu 1.8 private Set allowed_upcalls_methods(HMethod hm) { 778 salcianu 1.8 HClass hclass = hm.getDeclaringClass(); 779 salcianu 1.8 780 salcianu 1.8 if(jl_Map.isSuperinterfaceOf(hclass) && 781 salcianu 1.8 "java.util".equals(hclass.getPackage())) 782 salcianu 1.8 return map_upcalls; 783 salcianu 1.8 else if((jl_Collection.isSuperinterfaceOf(hclass)) && 784 salcianu 1.8 "java.util".equals(hclass.getPackage())) 785 salcianu 1.8 return coll_upcalls; 786 salcianu 1.8 else 787 salcianu 1.8 return null; 788 salcianu 1.8 } 789 salcianu 1.8 790 salcianu 1.8 private void print_coll_hack_debug() { 791 salcianu 1.8 Util.print_collection(put_in_colls, "COLL_HACK: Put into collections"); 792 salcianu 1.8 Util.print_collection(keys_put_in_maps, "COLL_HACK: Map keys"); 793 salcianu 1.8 Util.print_collection(values_put_in_maps, "COLL_HACK: Map values"); 794 salcianu 1.8 } 795 salcianu 1.8 796 salcianu 1.8 // COLL_HACK methods END 797 salcianu 1.8 798 salcianu 1.1.2.1 // "rec" generates all the possible combinations of types for the 799 salcianu 1.1.2.1 // parameters of "hm", generates metamethods, records the caller-callee 800 salcianu 1.1.2.1 // interactions and add the new metamethods to the worklist of metamethods. 801 salcianu 1.1.2.1 private void rec(HMethod hm, CALL cs, int pos, int max_pos){ 802 salcianu 1.1.2.1 if(pos == max_pos){ 803 salcianu 1.1.2.1 // all the types have been specialized 804 salcianu 1.1.2.1 specialize_the_call(hm,cs); 805 salcianu 1.1.2.1 return; 806 salcianu 1.1.2.1 } 807 salcianu 1.1.2.1 808 salcianu 1.1.2.1 if(cs.paramType(pos).isPrimitive()){ 809 salcianu 1.5 param_types[pos] = new GenType(cs.paramType(pos), GenType.MONO); 810 salcianu 1.5 rec(hm, cs, pos+1, max_pos); 811 salcianu 1.1.2.1 return; 812 salcianu 1.1.2.1 } 813 salcianu 1.1.2.1 814 salcianu 1.1.2.24 // For any possible ExactType T of the pos-th param, set 815 salcianu 1.1.2.24 // param_types[pos] to it and recurse on the remaining params. 816 salcianu 1.1.2.24 ExactTemp et = getExactTemp(cs.params(pos), cs, ExactTemp.USE); 817 salcianu 1.1.2.24 818 salcianu 1.5 assert !et.getTypeSet().isEmpty() : 819 salcianu 1.5 "\nNo possible type detected for " + et.t + 820 salcianu 1.5 "\n in method " + cs.getFactory().getMethod() + 821 salcianu 1.5 "\n at instr " + cs.getSourceFile() + ":" + 822 salcianu 1.5 cs.getLineNumber() + " " + cs; 823 salcianu 1.1.2.24 824 salcianu 1.1.2.24 for(Iterator it_types = et.getTypes(); it_types.hasNext(); ) { 825 salcianu 1.1.2.24 GenType gt = (GenType) it_types.next(); 826 salcianu 1.1.2.24 param_types[pos] = gt; 827 salcianu 1.1.2.24 rec(hm, cs, pos+1, max_pos); 828 salcianu 1.1.2.1 } 829 salcianu 1.5 830 salcianu 1.1.2.1 } 831 salcianu 1.1.2.1 832 salcianu 1.1.2.23 833 salcianu 1.1.2.1 // Checks whether calling "hm" starts a thread or not. 834 salcianu 1.1.2.1 private boolean thread_start_site(HMethod hm){ 835 salcianu 1.1.2.1 String name = hm.getName(); 836 salcianu 1.1.2.1 if(hm.getParameterNames().length != 0) return false; 837 salcianu 1.1.2.1 if((name==null) || !name.equals("start")) return false; 838 salcianu 1.1.2.1 if(hm.isStatic()) return false; 839 salcianu 1.1.2.1 HClass hclass = hm.getDeclaringClass(); 840 salcianu 1.1.2.1 return hclass.getName().equals("java.lang.Thread"); 841 salcianu 1.1.2.1 } 842 salcianu 1.1.2.1 843 salcianu 1.1.2.1 // Examine a possible thread start site 844 salcianu 1.1.2.13 private boolean check_thread_start_site(CALL cs){ 845 salcianu 1.1.2.13 if(!thread_start_site(cs.method())) return false; 846 salcianu 1.1.2.1 847 salcianu 1.1.2.23 boolean found_a_run = false; 848 salcianu 1.1.2.23 849 salcianu 1.1.2.24 // etbase.t points to the receiver class 850 salcianu 1.1.2.24 ExactTemp etbase = getExactTemp(cs.params(0), cs, ExactTemp.USE); 851 salcianu 1.1.2.13 852 salcianu 1.1.2.24 for(Iterator it_gt = etbase.getTypes(); it_gt.hasNext(); ) { 853 salcianu 1.1.2.24 GenType gt = (GenType) it_gt.next(); 854 salcianu 1.1.2.24 Set cls = gt.isPOLY() ? 855 salcianu 1.1.2.24 get_instantiated_children(gt.getHClass()) : 856 salcianu 1.1.2.24 Collections.singleton(gt.getHClass()); 857 salcianu 1.1.2.24 858 salcianu 1.1.2.24 for(Iterator it_cls = cls.iterator(); it_cls.hasNext(); ) { 859 salcianu 1.1.2.24 boolean hr = has_a_run(cs, (HClass) it_cls.next()); 860 salcianu 1.1.2.24 found_a_run = found_a_run || hr; 861 salcianu 1.1.2.13 } 862 salcianu 1.1.2.1 } 863 salcianu 1.1.2.23 864 salcianu 1.1.2.23 // The 2nd possibility of launching a thread a Java: calling 865 salcianu 1.1.2.23 // start() on a Thread object that doesn't implement run() but 866 salcianu 1.1.2.23 // points to a Runnable object. 867 salcianu 1.1.2.23 // We have to do a very conservative analysis here: examine ANY 868 salcianu 1.1.2.23 // object that implements Runnable and take its run method. 869 salcianu 1.1.2.23 870 salcianu 1.1.2.24 Set runnables = get_instantiated_children(jl_Runnable); 871 salcianu 1.1.2.23 for(Iterator it_cls = runnables.iterator(); it_cls.hasNext(); ) { 872 salcianu 1.1.2.23 boolean hr = has_a_run(cs, (HClass) it_cls.next()); 873 salcianu 1.1.2.23 found_a_run = found_a_run || hr; 874 salcianu 1.1.2.23 } 875 salcianu 1.1.2.13 876 cananian 1.3.2.1 assert found_a_run : "No run method was found for " + cs; 877 salcianu 1.1.2.13 878 salcianu 1.1.2.13 return true; 879 salcianu 1.1.2.1 } 880 salcianu 1.1.2.1 881 salcianu 1.1.2.23 // Check if hclass has a "run" method. If positive, this method 882 salcianu 1.1.2.23 // could be started as a thread body; it must be put in the meta method 883 salcianu 1.1.2.23 // worklist if it hasn't been seen before. 884 salcianu 1.1.2.23 private boolean has_a_run(CALL cs, HClass hclass){ 885 salcianu 1.1.2.1 HMethod run = null; 886 salcianu 1.1.2.1 887 salcianu 1.1.2.1 HMethod[] hms = hclass.getMethods(); 888 salcianu 1.1.2.1 for(int i = 0; i < hms.length ; i++){ 889 salcianu 1.1.2.1 if(!hms[i].getName().equals("run")) continue; 890 salcianu 1.1.2.1 int modifs = hms[i].getModifiers(); 891 salcianu 1.1.2.1 if(Modifier.isAbstract(modifs) || 892 salcianu 1.1.2.1 Modifier.isStatic(modifs) || 893 salcianu 1.1.2.1 Modifier.isNative(modifs) || 894 salcianu 1.1.2.1 !Modifier.isPublic(modifs)) continue; 895 salcianu 1.1.2.1 if(hms[i].getParameterNames().length != 0) continue; 896 salcianu 1.1.2.1 run = hms[i]; 897 salcianu 1.1.2.1 break; 898 salcianu 1.1.2.1 } 899 salcianu 1.1.2.1 900 salcianu 1.1.2.23 if(run == null) return false; 901 salcianu 1.1.2.1 902 salcianu 1.1.2.1 // create a new MetaMethod corresponding to the run method and try 903 salcianu 1.1.2.1 // to put it into the worklist if it's really new. 904 salcianu 1.1.2.1 GenType gtbase = new GenType(hclass,GenType.MONO); 905 salcianu 1.1.2.1 MetaMethod mm = new MetaMethod(run,new GenType[]{gtbase}); 906 salcianu 1.1.2.1 if(!analyzed_mm.contains(mm)) 907 salcianu 1.1.2.1 WMM.add(mm); 908 salcianu 1.1.2.12 909 salcianu 1.1.2.13 run_mms.add(mm); 910 salcianu 1.1.2.1 911 salcianu 1.1.2.23 // if(DEBUG) 912 salcianu 1.1.2.26 System.out.println("\nTHREAD START SITE:" + 913 salcianu 1.1.2.13 cs.getSourceFile() + ":" + 914 salcianu 1.1.2.13 cs.getLineNumber() + " " + 915 salcianu 1.1.2.13 cs + " => " + mm); 916 salcianu 1.1.2.23 return true; 917 salcianu 1.1.2.1 } 918 salcianu 1.1.2.1 919 salcianu 1.1.2.24 private long call_time = 0L; 920 salcianu 1.1.2.24 private int nb_calls = 0; 921 salcianu 1.1.2.24 private int nb_big_calls = 0; 922 salcianu 1.1.2.24 923 salcianu 1.1.2.1 // analyze the CALL site "cs" inside the MetaMethod "mm". 924 salcianu 1.1.2.24 private void analyze_one_call(CALL cs) { 925 salcianu 1.1.2.1 HMethod hm = cs.method(); 926 salcianu 1.1.2.1 int nb_params = cs.paramsLength(); 927 salcianu 1.1.2.1 param_types = new GenType[nb_params]; 928 salcianu 1.1.2.1 929 salcianu 1.8 if(DEBUG) 930 salcianu 1.8 System.out.println("$$:analyze_call(" + cs + ")"); 931 salcianu 1.1.2.1 932 salcianu 1.1.2.1 // for 'special' invocations, we know the method exactly 933 salcianu 1.8 if(!cs.isVirtual() || cs.isStatic()) { 934 salcianu 1.1.2.1 if(DEBUG) System.out.println("//: " + cs); 935 salcianu 1.1.2.23 if(Modifier.isNative(hm.getModifiers())) 936 salcianu 1.1.2.23 check_thread_start_site(cs); 937 salcianu 1.1.2.1 rec(hm,cs,0,nb_params); 938 salcianu 1.1.2.1 return; 939 salcianu 1.1.2.1 } 940 salcianu 1.1.2.1 941 salcianu 1.8 check_thread_start_site(cs); 942 salcianu 1.8 943 salcianu 1.1.2.1 // for native methods, specialization doesn't make any sense 944 salcianu 1.1.2.1 // because we cannot analyze their body. 945 salcianu 1.8 if(TOUGH_ON_NATIVES && Modifier.isNative(hm.getModifiers())) { 946 salcianu 1.8 param_types[0] = 947 salcianu 1.8 new GenType(hm.getDeclaringClass(), GenType.POLY); 948 salcianu 1.1.2.1 HClass[] types = hm.getParameterTypes(); 949 salcianu 1.1.2.1 for(int i = 0; i < types.length; i++) 950 salcianu 1.1.2.1 param_types[i+1] = new GenType(types[i],GenType.POLY); 951 salcianu 1.1.2.15 specialize_the_call(hm, cs); 952 salcianu 1.1.2.1 return; 953 salcianu 1.1.2.1 } 954 salcianu 1.1.2.1 955 salcianu 1.1.2.1 nb_meta_methods = 0; 956 salcianu 1.1.2.1 957 salcianu 1.1.2.1 if(nb_params == 0) 958 cananian 1.3.2.1 assert false : "Non static method with no parameters " + cs; 959 salcianu 1.1.2.1 960 salcianu 1.1.2.1 // the first parameter (the method receiver) must be treated specially 961 salcianu 1.1.2.24 ExactTemp etbase = getExactTemp(cs.params(0), cs, ExactTemp.USE); 962 salcianu 1.1.2.24 if(CAUTION && etbase.getTypeSet().isEmpty()) 963 cananian 1.3.2.1 assert false : "No possible type detected for " + etbase; 964 salcianu 1.1.2.1 965 salcianu 1.1.2.24 boolean poly = false; 966 salcianu 1.1.2.1 967 salcianu 1.1.2.24 long start = time(); 968 salcianu 1.1.2.24 969 salcianu 1.1.2.24 for(Iterator it_types = etbase.getTypes(); it_types.hasNext(); ) { 970 salcianu 1.1.2.24 GenType gt = (GenType) it_types.next(); 971 salcianu 1.1.2.24 if(gt.isPOLY()) { 972 salcianu 1.1.2.24 poly = true; 973 salcianu 1.1.2.24 treat_poly_base(hm, cs, gt); 974 salcianu 1.1.2.1 } 975 salcianu 1.1.2.24 else 976 salcianu 1.1.2.24 treat_mono_base(hm, cs, gt); 977 salcianu 1.1.2.1 } 978 salcianu 1.1.2.1 979 salcianu 1.1.2.24 call_time += time() - start; 980 salcianu 1.1.2.24 nb_calls++; 981 salcianu 1.1.2.24 982 salcianu 1.1.2.1 if(DEBUG) 983 salcianu 1.1.2.1 System.out.println("||: " + cs + " calls " + nb_meta_methods + 984 salcianu 1.1.2.1 " meta-method(s)"); 985 salcianu 1.1.2.1 986 salcianu 1.1.2.24 if(DEBUG_CH && (nb_meta_methods == 0)) { 987 salcianu 1.1.2.24 System.out.println("ALARM!<\n" + " mm = " + mm_work + 988 salcianu 1.1.2.24 "\n " + 989 salcianu 1.1.2.24 (poly ? "POLY" : "MONO") + 990 salcianu 1.10 " cs = " + Util.code2str(cs) + 991 salcianu 1.1.2.24 "> 0 callees!"); 992 salcianu 1.1.2.24 // display the SCC of exact temps and their types 993 salcianu 1.1.2.24 display_mm_data(mm_work); 994 salcianu 1.1.2.3 } 995 salcianu 1.1.2.3 996 salcianu 1.1.2.1 param_types = null; // enable the GC 997 salcianu 1.1.2.1 } 998 salcianu 1.1.2.1 999 salcianu 1.1.2.24 private void display_mm_data(MetaMethod mm) { 1000 salcianu 1.1.2.24 HMethod hm = mm_work.getHMethod(); 1001 salcianu 1.1.2.24 MethodData md = get_method_data(hm); 1002 salcianu 1.7 System.out.println("\n\nDATA FOR " + mm_work + ":"); 1003 salcianu 1.1.2.24 System.out.println(md); 1004 salcianu 1.7 System.out.println("\nCOMPUTED TYPES:"); 1005 salcianu 1.14 for(SCComponent scc : md.sccs) { 1006 salcianu 1.15 for(Object etO : scc.nodes()) { 1007 cananian 1.12 ExactTemp et = (ExactTemp) etO; 1008 salcianu 1.1.2.24 System.out.println("< " + et.t + ", " + 1009 salcianu 1.13 ((et.ud == ExactTemp.USE) ? "USE" : "DEF") + 1010 salcianu 1.10 ", " + Util.code2str(et.q) + 1011 salcianu 1.1.2.24 " > has type(s) {"); 1012 salcianu 1.1.2.24 for(Iterator it2 = et.getTypes(); it2.hasNext(); ) 1013 salcianu 1.1.2.24 System.out.println("\t" + ((GenType) it2.next())); 1014 salcianu 1.1.2.24 System.out.println("}"); 1015 salcianu 1.1.2.24 } 1016 salcianu 1.13 } 1017 salcianu 1.1.2.24 1018 salcianu 1.7 System.out.println("\nCODE:"); 1019 salcianu 1.1.2.28 HCode hcode = hcf.convert(hm); 1020 salcianu 1.1.2.24 hcode.print(new java.io.PrintWriter(System.out, true)); 1021 salcianu 1.1.2.24 System.out.println("--------------------------------------"); 1022 salcianu 1.1.2.24 } 1023 salcianu 1.1.2.24 1024 salcianu 1.1.2.24 1025 salcianu 1.1.2.1 // Treat the case of a polymorphic type for the receiver of the method hm 1026 salcianu 1.1.2.24 private void treat_poly_base(HMethod hm, CALL cs, GenType gt) { 1027 salcianu 1.1.2.24 Set classes = get_possible_classes(gt.getHClass(), hm); 1028 salcianu 1.1.2.24 1029 salcianu 1.1.2.24 // compute the set of objects that actually provide an 1030 salcianu 1.1.2.24 // implementation for the method hm 1031 salcianu 1.1.2.24 implementers.clear(); 1032 salcianu 1.1.2.24 nb_cls = 0; 1033 cananian 1.12 for(Object cO : classes) { 1034 cananian 1.12 HClass c = (HClass) cO; 1035 salcianu 1.1.2.1 // fix some strange bug 1036 salcianu 1.1.2.1 if(c.isPrimitive()) continue; 1037 salcianu 1.1.2.24 HMethod callee = c.getMethod(hm.getName(), hm.getDescriptor()); 1038 salcianu 1.1.2.24 HClass dc = callee.getDeclaringClass(); 1039 salcianu 1.1.2.24 implementers.add(dc); 1040 salcianu 1.1.2.24 cls[nb_cls] = c; 1041 salcianu 1.1.2.24 impl[nb_cls] = dc; 1042 salcianu 1.1.2.24 nb_cls++; 1043 salcianu 1.1.2.24 } 1044 salcianu 1.1.2.24 1045 salcianu 1.1.2.24 nb_big_calls++; 1046 salcianu 1.1.2.24 1047 cananian 1.12 for(Object cO : implementers) { 1048 cananian 1.12 HClass c = (HClass) cO; 1049 salcianu 1.1.2.24 HMethod callee = c.getMethod(hm.getName(), hm.getDescriptor()); 1050 salcianu 1.1.2.24 1051 salcianu 1.1.2.24 nb_kids = 0; 1052 salcianu 1.1.2.24 for(int i = 0; i < nb_cls; i++) 1053 salcianu 1.1.2.24 if(c.equals(impl[i])) 1054 salcianu 1.1.2.24 kids[nb_kids++] = cls[i]; 1055 salcianu 1.1.2.24 1056 salcianu 1.1.2.24 if(nb_kids > SPEC_BOUND) { 1057 salcianu 1.1.2.24 param_types[0] = new GenType(c, GenType.POLY); 1058 salcianu 1.1.2.24 rec(callee, cs, 1, cs.paramsLength()); 1059 salcianu 1.1.2.24 } 1060 salcianu 1.1.2.24 else { 1061 salcianu 1.1.2.24 for(int i = 0; i < nb_kids; i++) { 1062 salcianu 1.1.2.24 param_types[0] = new GenType(kids[i], GenType.MONO); 1063 salcianu 1.1.2.24 rec(callee, cs, 1, cs.paramsLength()); 1064 salcianu 1.1.2.24 } 1065 salcianu 1.1.2.24 } 1066 salcianu 1.1.2.1 } 1067 salcianu 1.1.2.1 } 1068 salcianu 1.1.2.24 private Set implementers = new HashSet(); 1069 salcianu 1.1.2.24 private HClass kids[] = new HClass[1000]; 1070 salcianu 1.1.2.24 private int nb_kids = 0; 1071 salcianu 1.1.2.24 private HClass cls[] = new HClass[1000]; 1072 salcianu 1.1.2.24 private HClass impl[] = new HClass[1000]; 1073 salcianu 1.1.2.24 private int nb_cls = 0; 1074 salcianu 1.1.2.24 1075 salcianu 1.1.2.24 // Returns the set of all the instantiated (sub)classes of root 1076 salcianu 1.1.2.24 // (including root) that implement the method "hm". 1077 salcianu 1.1.2.24 private Set get_possible_classes(HClass root, HMethod hm) { 1078 salcianu 1.1.2.24 Set children = 1079 salcianu 1.1.2.24 get_instantiated_children(root); 1080 salcianu 1.8 1081 salcianu 1.1.2.1 Set possible_classes = new HashSet(); 1082 salcianu 1.1.2.1 1083 cananian 1.12 for(Object cO : children) { 1084 cananian 1.12 HClass c = (HClass) cO; 1085 salcianu 1.1.2.24 if(Modifier.isAbstract(c.getModifiers())) 1086 salcianu 1.1.2.24 continue; 1087 salcianu 1.1.2.1 boolean implemented = true; 1088 salcianu 1.1.2.1 HMethod callee = null; 1089 salcianu 1.1.2.1 try{ 1090 salcianu 1.1.2.24 callee = c.getMethod(hm.getName(), hm.getDescriptor()); 1091 salcianu 1.1.2.1 }catch(NoSuchMethodError nsme){ 1092 salcianu 1.1.2.1 implemented = false; 1093 salcianu 1.1.2.1 } 1094 salcianu 1.1.2.1 if(implemented && !Modifier.isAbstract(callee.getModifiers())) 1095 salcianu 1.1.2.1 possible_classes.add(c); 1096 salcianu 1.1.2.1 } 1097 salcianu 1.1.2.1 1098 salcianu 1.1.2.1 return possible_classes; 1099 salcianu 1.1.2.1 } 1100 salcianu 1.8 1101 salcianu 1.8 private Set get_instantiated_children(GenType gt) { 1102 salcianu 1.8 HClass hclass = gt.getHClass(); 1103 salcianu 1.8 if(gt.isPOLY()) 1104 salcianu 1.8 return get_instantiated_children(hclass); 1105 salcianu 1.8 else if(instantiated_classes.contains(hclass)) 1106 salcianu 1.8 return Collections.singleton(hclass); 1107 salcianu 1.8 else 1108 salcianu 1.8 return Collections.EMPTY_SET; 1109 salcianu 1.8 } 1110 salcianu 1.1.2.1 1111 salcianu 1.1.2.1 // Returns the set of all the subclasses of class root that could 1112 salcianu 1.1.2.1 // be instantiated by the program. 1113 salcianu 1.1.2.24 Set get_instantiated_children(HClass root){ 1114 salcianu 1.1.2.1 Set children = new HashSet(); 1115 salcianu 1.1.2.1 PAWorkList Wc = new PAWorkList(); 1116 salcianu 1.1.2.1 Wc.add(root); 1117 salcianu 1.1.2.24 while(!Wc.isEmpty()) { 1118 salcianu 1.1.2.1 HClass c = (HClass) Wc.remove(); 1119 salcianu 1.1.2.24 if(instantiated_classes.contains(c)) 1120 salcianu 1.1.2.1 children.add(c); 1121 salcianu 1.1.2.24 for(Iterator it = ch.children(c).iterator(); it.hasNext(); ) 1122 salcianu 1.1.2.24 Wc.add(it.next()); 1123 salcianu 1.1.2.1 } 1124 salcianu 1.1.2.1 return children; 1125 salcianu 1.1.2.1 } 1126 salcianu 1.1.2.1 1127 salcianu 1.1.2.1 // Treat the case of a monomorphyc type for the receiver of the method hm 1128 salcianu 1.1.2.24 private void treat_mono_base(HMethod hm, CALL cs, GenType gt) { 1129 salcianu 1.1.2.1 HClass c = gt.getHClass(); 1130 salcianu 1.1.2.3 // fix some strange bug: HClass.Void keeps appearing here! 1131 salcianu 1.1.2.1 if(c.isPrimitive()) return; 1132 salcianu 1.1.2.24 1133 salcianu 1.1.2.24 //System.out.println("SMALL call " + cs); 1134 salcianu 1.1.2.24 1135 salcianu 1.1.2.1 HMethod callee = null; 1136 salcianu 1.1.2.1 boolean implements_hm = true; 1137 salcianu 1.1.2.1 try{ 1138 salcianu 1.1.2.24 callee = c.getMethod(hm.getName(), hm.getDescriptor()); 1139 salcianu 1.1.2.1 } 1140 salcianu 1.1.2.1 catch(NoSuchMethodError nsme){ 1141 salcianu 1.1.2.24 System.out.println("treat_mono_base: " + 1142 salcianu 1.10 Util.code2str(cs) + " " + nsme); 1143 salcianu 1.1.2.1 implements_hm = false; 1144 salcianu 1.1.2.1 } 1145 salcianu 1.1.2.24 1146 salcianu 1.1.2.24 //System.out.println(" callee = " + callee); 1147 salcianu 1.1.2.24 1148 salcianu 1.1.2.1 if(implements_hm && !Modifier.isAbstract(callee.getModifiers())){ 1149 salcianu 1.1.2.1 param_types[0] = gt; 1150 salcianu 1.1.2.24 rec(callee, cs, 1, cs.paramsLength()); 1151 salcianu 1.1.2.1 } 1152 salcianu 1.1.2.1 } 1153 salcianu 1.1.2.1 1154 salcianu 1.1.2.1 ////// "analyze_one_call" related stuff END =========== 1155 salcianu 1.1.2.1 1156 salcianu 1.1.2.24 1157 salcianu 1.1.2.24 // Computes the set of the exact temps we are interested in 1158 salcianu 1.1.2.24 // (the arguments of the CALLs from the code of the analyzed method). 1159 salcianu 1.5 private final Set get_initial_set(ReachingDefs rdef, Collection calls) { 1160 salcianu 1.1.2.24 Set initial_set = new HashSet(); 1161 cananian 1.12 for(Object qO : calls) { 1162 cananian 1.12 CALL q = (CALL) qO; 1163 salcianu 1.1.2.1 int nb_params = q.paramsLength(); 1164 salcianu 1.1.2.1 for(int i = 0; i < nb_params; i++) 1165 salcianu 1.1.2.24 if(!q.paramType(i).isPrimitive()) { 1166 salcianu 1.1.2.1 Temp t = q.params(i); 1167 salcianu 1.1.2.24 initial_set.add(getExactTemp(t, q, ExactTemp.USE)); 1168 salcianu 1.1.2.1 } 1169 salcianu 1.1.2.1 } 1170 salcianu 1.1.2.24 1171 salcianu 1.1.2.24 return initial_set; 1172 salcianu 1.1.2.1 } 1173 salcianu 1.1.2.1 1174 salcianu 1.1.2.1 // Data attached to a method 1175 salcianu 1.1.2.24 private class MethodData { 1176 salcianu 1.13 // The SCCs (in decreasing topological order) 1177 salcianu 1.14 List<SCComponent/*<??>*/> sccs; 1178 salcianu 1.1.2.24 // The ets2et map for this method (see the comments around ets2et) 1179 salcianu 1.1.2.1 Map ets2et; 1180 salcianu 1.1.2.24 // The set of CALL quads occuring in the code of the method 1181 salcianu 1.5 Collection calls; 1182 salcianu 1.1.2.24 1183 salcianu 1.14 MethodData(List<SCComponent/*<>*/> sccs, 1184 salcianu 1.13 Map ets2et, Collection calls) { 1185 salcianu 1.13 this.sccs = sccs; 1186 salcianu 1.1.2.1 this.ets2et = ets2et; 1187 salcianu 1.1.2.24 this.calls = calls; 1188 salcianu 1.1.2.24 } 1189 salcianu 1.1.2.24 1190 salcianu 1.1.2.24 public String toString() { 1191 salcianu 1.1.2.24 StringBuffer buff = new StringBuffer(); 1192 salcianu 1.1.2.24 buff.append("SCC(s):\n" ); 1193 salcianu 1.14 for(SCComponent scc : sccs) { 1194 salcianu 1.1.2.24 buff.append(scc.toString()); 1195 salcianu 1.1.2.24 } 1196 salcianu 1.1.2.24 buff.append("CALL(s):"); 1197 salcianu 1.1.2.24 for(Iterator it = calls.iterator(); it.hasNext(); ) 1198 salcianu 1.1.2.24 buff.append("\n " + it.next().toString()); 1199 salcianu 1.1.2.24 return buff.toString(); 1200 salcianu 1.1.2.1 } 1201 salcianu 1.1.2.1 } 1202 salcianu 1.1.2.1 1203 salcianu 1.7 // return an appropriate impl. of ReachingDefs for hcode 1204 salcianu 1.7 private ReachingDefs getReachingDefsImpl(HCode hcode) { 1205 salcianu 1.7 if(ssx_form) 1206 salcianu 1.7 return new SSxReachingDefsImpl(hcode); 1207 salcianu 1.7 else 1208 salcianu 1.7 return new ReachingDefsImpl(hcode); 1209 salcianu 1.7 } 1210 salcianu 1.7 1211 salcianu 1.1.2.1 // Map<HMethod,MethodData> 1212 salcianu 1.1.2.1 private Map mh2md = new HashMap(); 1213 salcianu 1.1.2.1 // Adds some caching over "compute_md". 1214 salcianu 1.8 private MethodData get_method_data(HMethod hm) { 1215 salcianu 1.1.2.1 MethodData md = (MethodData) mh2md.get(hm); 1216 salcianu 1.5 if(md == null) { // if not in the cache, build it from scratch 1217 salcianu 1.1.2.28 HCode hcode = hcf.convert(hm); 1218 salcianu 1.5 Collection calls = ((Code) hcode).selectCALLs(); 1219 salcianu 1.1.2.1 // initialize the ets2et map (see the comments near its definition) 1220 salcianu 1.1.2.24 ets2et = new HashMap(); 1221 salcianu 1.7 ReachingDefs rdef = getReachingDefsImpl(hcode); 1222 salcianu 1.14 md = new MethodData(compute_sccs(get_initial_set(rdef, calls), 1223 salcianu 1.14 rdef), 1224 salcianu 1.14 ets2et, calls); 1225 salcianu 1.1.2.24 mh2md.put(hm, md); 1226 salcianu 1.1.2.1 } 1227 salcianu 1.1.2.1 return md; 1228 salcianu 1.1.2.1 } 1229 salcianu 1.1.2.1 1230 salcianu 1.1.2.1 1231 salcianu 1.1.2.24 // an "exact" temp: the Temp "t" defined in the Quad "q" 1232 salcianu 1.1.2.24 private class ExactTemp { 1233 salcianu 1.1.2.24 1234 salcianu 1.1.2.24 Temp t; // the Temp t that is 1235 salcianu 1.1.2.24 int ud; // defined/used in 1236 salcianu 1.1.2.24 Quad q; // quad q 1237 salcianu 1.1.2.24 1238 salcianu 1.1.2.24 static final int DEF = 0; 1239 salcianu 1.1.2.24 static final int USE = 1; 1240 salcianu 1.1.2.1 1241 salcianu 1.1.2.1 // Set<GenType> - the possible types of this ExactTemp. 1242 salcianu 1.1.2.24 Set gtypes; 1243 salcianu 1.1.2.1 1244 salcianu 1.1.2.24 // The ExactTemps whose types are influenced by the type of this one. 1245 salcianu 1.1.2.1 ExactTemp[] next = new ExactTemp[0]; 1246 salcianu 1.1.2.24 // The ExactTemps whose types influence the type of this one. 1247 salcianu 1.1.2.1 ExactTemp[] prev = new ExactTemp[0]; 1248 salcianu 1.1.2.1 1249 salcianu 1.1.2.24 ExactTemp(Temp t, Quad q, int ud){ 1250 salcianu 1.1.2.24 this.t = t; 1251 salcianu 1.1.2.24 this.q = q; 1252 salcianu 1.1.2.24 this.ud = ud; 1253 salcianu 1.1.2.24 this.gtypes = new HashSet(); 1254 salcianu 1.1.2.1 } 1255 salcianu 1.1.2.1 1256 salcianu 1.1.2.1 /** Returns an iterator over the set of all the possible types 1257 salcianu 1.1.2.1 for <code>this</code> <code>ExactTemp</code>. */ 1258 salcianu 1.1.2.3 Iterator getTypes(){ 1259 salcianu 1.1.2.1 return gtypes.iterator(); 1260 salcianu 1.1.2.1 } 1261 salcianu 1.1.2.1 1262 salcianu 1.1.2.1 /** Returns the set of all the possible types 1263 salcianu 1.1.2.1 for <code>this</code> <code>ExactTemp</code>. */ 1264 salcianu 1.1.2.3 Set getTypeSet(){ 1265 salcianu 1.1.2.1 return gtypes; 1266 salcianu 1.1.2.1 } 1267 salcianu 1.1.2.1 1268 salcianu 1.1.2.3 /** Clears the set of possible types for <code>this</code> ExactTemp.*/ 1269 salcianu 1.1.2.3 void clearTypeSet(){ 1270 salcianu 1.1.2.3 gtypes.clear(); 1271 salcianu 1.1.2.3 } 1272 salcianu 1.1.2.3 1273 salcianu 1.1.2.1 /** Adds the type <code>gt</code> to the set of possible 1274 salcianu 1.1.2.1 types for <code>this</code> <code>ExactTemp</code>. */ 1275 salcianu 1.1.2.1 void addType(GenType type){ 1276 salcianu 1.1.2.1 1277 salcianu 1.1.2.1 if(type.isPOLY()){ 1278 salcianu 1.1.2.1 // TODO : add some caching here 1279 salcianu 1.1.2.24 Set children = get_instantiated_children(type.getHClass()); 1280 salcianu 1.1.2.1 if(children.size() == 1) 1281 salcianu 1.1.2.1 type = new GenType((HClass)children.iterator().next(), 1282 salcianu 1.1.2.1 GenType.MONO); 1283 salcianu 1.1.2.1 } 1284 salcianu 1.1.2.1 1285 salcianu 1.5 List to_remove = new LinkedList(); 1286 salcianu 1.1.2.1 1287 cananian 1.12 for(Object gtO : gtypes){ 1288 cananian 1.12 GenType gt = (GenType) gtO; 1289 salcianu 1.5 // no new information here 1290 salcianu 1.5 if(type.included(gt, ch)) 1291 salcianu 1.1.2.1 return; 1292 salcianu 1.5 // the new information we add makes some old one redundant 1293 salcianu 1.5 if(gt.included(type, ch)) 1294 salcianu 1.1.2.1 to_remove.add(type); 1295 salcianu 1.1.2.1 } 1296 salcianu 1.1.2.1 1297 salcianu 1.5 for(Iterator it = to_remove.iterator(); it.hasNext(); ) 1298 salcianu 1.5 gtypes.remove((GenType) it.next()); 1299 salcianu 1.1.2.1 1300 salcianu 1.1.2.1 gtypes.add(type); 1301 salcianu 1.1.2.1 } 1302 salcianu 1.1.2.1 1303 salcianu 1.1.2.1 /** Adds the types from the set <code>gts</code> to the set of possible 1304 salcianu 1.1.2.1 types for <code>this</code> <code>ExactTemp</code>. */ 1305 salcianu 1.1.2.1 void addTypes(Set gts){ 1306 salcianu 1.1.2.1 for(Iterator it = gts.iterator(); it.hasNext();) 1307 salcianu 1.1.2.1 addType((GenType) it.next()); 1308 salcianu 1.1.2.1 } 1309 salcianu 1.1.2.1 1310 salcianu 1.1.2.3 String shortDescription(){ 1311 salcianu 1.1.2.24 return "<" + t.toString() + ", " + 1312 salcianu 1.1.2.24 ((ud == ExactTemp.DEF) ? "DEF" : "USE") + ", " + 1313 salcianu 1.10 Util.code2str(q) + ">"; 1314 salcianu 1.1.2.1 } 1315 salcianu 1.1.2.1 1316 salcianu 1.1.2.1 public String toString(){ 1317 salcianu 1.1.2.1 StringBuffer buffer = new StringBuffer(); 1318 salcianu 1.1.2.1 buffer.append(shortDescription()); 1319 salcianu 1.1.2.1 if((next.length == 0) && (prev.length == 0)){ 1320 salcianu 1.1.2.1 buffer.append("\n"); 1321 salcianu 1.1.2.1 return buffer.toString(); 1322 salcianu 1.1.2.1 } 1323 salcianu 1.1.2.1 buffer.append("(\n"); 1324 salcianu 1.1.2.1 if(next.length > 0){ 1325 salcianu 1.1.2.24 buffer.append("The following defs depends on this one:\n"); 1326 salcianu 1.1.2.1 for(int i = 0 ; i < next.length ; i++) 1327 salcianu 1.1.2.1 buffer.append(" " + 1328 salcianu 1.1.2.1 (next[i]==null?"null": 1329 salcianu 1.1.2.1 next[i].shortDescription()) + "\n"); 1330 salcianu 1.1.2.1 } 1331 salcianu 1.1.2.1 if(prev.length > 0){ 1332 salcianu 1.1.2.24 buffer.append("Depends on the following defs:\n"); 1333 salcianu 1.1.2.1 for(int i = 0 ; i < prev.length ; i++) 1334 salcianu 1.1.2.1 buffer.append(" " + prev[i].shortDescription() + "\n"); 1335 salcianu 1.1.2.1 } 1336 salcianu 1.1.2.1 buffer.append(")"); 1337 salcianu 1.1.2.1 return buffer.toString(); 1338 salcianu 1.1.2.1 } 1339 salcianu 1.1.2.1 } 1340 salcianu 1.1.2.1 1341 salcianu 1.1.2.1 1342 salcianu 1.1.2.1 ////// DEPENDENCY DETECTION (getDependencies) - BEGIN 1343 salcianu 1.1.2.1 1344 salcianu 1.1.2.24 // Quad visitor class for the dependency detection. This class is 1345 salcianu 1.1.2.24 // declared here (and not inside getDependencies as it were more elegant) 1346 salcianu 1.1.2.24 // such that we are able to allocate a single QuadVisitorDD for the 1347 salcianu 1.1.2.24 // entire meta call graph construction (instead of one for each analyzed 1348 salcianu 1.1.2.24 // ExactTemp). 1349 salcianu 1.1.2.24 private class QuadVisitorDD extends QuadVisitor { 1350 salcianu 1.1.2.24 1351 salcianu 1.1.2.24 ExactTemp[] deps = null; 1352 salcianu 1.1.2.24 Temp t = null; 1353 salcianu 1.5 int ud = ExactTemp.DEF; 1354 salcianu 1.1.2.24 ReachingDefs rdef = null; 1355 salcianu 1.1.2.24 1356 salcianu 1.1.2.24 public void visit(MOVE q) { 1357 salcianu 1.1.2.24 if(CAUTION && !t.equals(q.dst())) stop_no_def(q); 1358 salcianu 1.1.2.24 add_deps(q.src(), q); 1359 salcianu 1.1.2.24 } 1360 salcianu 1.1.2.24 1361 salcianu 1.1.2.24 public void visit(AGET q) { 1362 salcianu 1.1.2.24 if(CAUTION && !t.equals(q.dst())) stop_no_def(q); 1363 salcianu 1.1.2.24 add_deps(q.objectref(), q); 1364 salcianu 1.1.2.24 } 1365 salcianu 1.1.2.24 1366 salcianu 1.1.2.24 public void visit(CALL q) { 1367 salcianu 1.1.2.24 if(ud == ExactTemp.DEF) { 1368 salcianu 1.5 if(t.equals(q.retval()) || t.equals(q.retex())) { 1369 salcianu 1.5 // t's type will be determined by method signature 1370 salcianu 1.1.2.1 } 1371 salcianu 1.5 else 1372 salcianu 1.5 visit((SIGMA) q); 1373 salcianu 1.5 1374 salcianu 1.1.2.24 return; 1375 salcianu 1.1.2.1 } 1376 salcianu 1.5 1377 salcianu 1.1.2.24 Set rdefs = rdef.reachingDefs(q, t); 1378 salcianu 1.1.2.24 deps = new ExactTemp[rdefs.size()]; 1379 salcianu 1.1.2.24 Iterator it = rdefs.iterator(); 1380 salcianu 1.1.2.24 for(int i = 0; i < rdefs.size(); i++) { 1381 salcianu 1.1.2.24 Quad qdef = (Quad) it.next(); 1382 salcianu 1.1.2.24 deps[i] = getExactTemp(t, qdef, ExactTemp.DEF); 1383 salcianu 1.1.2.1 } 1384 salcianu 1.1.2.24 } 1385 salcianu 1.1.2.24 1386 salcianu 1.1.2.24 public void visit(NEW q) { 1387 salcianu 1.1.2.24 if(CAUTION && !t.equals(q.dst())) stop_no_def(q); 1388 salcianu 1.1.2.24 } 1389 salcianu 1.1.2.24 1390 salcianu 1.1.2.24 public void visit(ANEW q) { 1391 salcianu 1.1.2.24 if(CAUTION && !t.equals(q.dst())) stop_no_def(q); 1392 salcianu 1.1.2.24 } 1393 salcianu 1.1.2.24 1394 salcianu 1.1.2.24 public void visit(TYPECAST q) { 1395 salcianu 1.5 /* 1396 salcianu 1.5 System.out.println 1397 salcianu 1.5 ("\n\ttypecast: " + 1398 salcianu 1.10 harpoon.Analysis.PointerAnalysis.Util.code2str(q) + "\n"); 1399 salcianu 1.5 */ 1400 salcianu 1.5 1401 salcianu 1.1.2.24 if(CAUTION && !t.equals(q.objectref())) stop_no_def(q); 1402 salcianu 1.1.2.24 } 1403 salcianu 1.1.2.24 1404 salcianu 1.1.2.24 public void visit(GET q) { 1405 salcianu 1.1.2.24 if(CAUTION && !t.equals(q.dst())) stop_no_def(q); 1406 salcianu 1.1.2.24 } 1407 salcianu 1.1.2.24 1408 salcianu 1.1.2.24 public void visit(METHOD q) { 1409 salcianu 1.1.2.24 // do nothing: the type of "et" defined here does not 1410 salcianu 1.1.2.24 // depend on any other ExactType's type. 1411 salcianu 1.5 if(CAUTION) { 1412 salcianu 1.1.2.24 boolean found = false; 1413 salcianu 1.1.2.24 for(int i = 0; i < q.paramsLength(); i++) 1414 salcianu 1.5 if(q.params(i).equals(t)) { 1415 salcianu 1.1.2.24 found = true; 1416 salcianu 1.1.2.24 break; 1417 salcianu 1.1.2.24 } 1418 salcianu 1.1.2.24 if(!found) stop_no_def(q); 1419 salcianu 1.1.2.1 } 1420 salcianu 1.1.2.24 } 1421 salcianu 1.1.2.24 1422 salcianu 1.1.2.24 public void visit(CONST q) { 1423 salcianu 1.1.2.24 if(CAUTION && !t.equals(q.dst())) stop_no_def(q); 1424 salcianu 1.1.2.24 } 1425 salcianu 1.5 1426 salcianu 1.5 1427 salcianu 1.5 // SSI additions BEGIN 1428 salcianu 1.5 public void visit(PHI q) { 1429 salcianu 1.5 int numPhis = q.numPhis(); 1430 salcianu 1.5 for(int i = 0; i < numPhis; i++) 1431 salcianu 1.5 if(t.equals(q.dst(i))) { 1432 salcianu 1.5 add_deps(q.src(i), q); 1433 salcianu 1.5 return; 1434 salcianu 1.5 } 1435 salcianu 1.5 1436 salcianu 1.5 stop_no_def(q); 1437 salcianu 1.5 } 1438 salcianu 1.5 1439 salcianu 1.5 1440 salcianu 1.5 // recognize the translation of a TYPECAST in QuadSSI: 1441 salcianu 1.5 // a CJMP t2 preceded by a t2 = t INSTANCEOF hclass; treat it 1442 salcianu 1.5 // as a TYPECAST 1443 salcianu 1.5 public void visit(CJMP q) { 1444 salcianu 1.7 if(ssx_form && (is_typecast(q, t) != null)) { 1445 salcianu 1.5 // do nothing; t's type will be determined by the typecast 1446 salcianu 1.7 } 1447 salcianu 1.7 else if(is_nulltest(q, t)) { 1448 salcianu 1.7 // Once again, do nothing 1449 salcianu 1.7 // t will be null, ie HClass.Void 1450 salcianu 1.5 } 1451 salcianu 1.5 else 1452 salcianu 1.5 visit((SIGMA) q); 1453 salcianu 1.5 } 1454 salcianu 1.5 1455 salcianu 1.5 1456 salcianu 1.5 public void visit(SIGMA q) { 1457 salcianu 1.5 int numSigmas = q.numSigmas(); 1458 salcianu 1.5 for(int i = 0; i < numSigmas; i++) { 1459 salcianu 1.5 // src(i) goes into dst(i)[0] ... dst(i)[dst.length-1] 1460 salcianu 1.5 Temp dst[] = q.dst(i); 1461 salcianu 1.5 for(int j = 0; j < dst.length; j++) 1462 salcianu 1.5 if(t.equals(dst[j])) { 1463 salcianu 1.5 add_deps(q.src(i), q); 1464 salcianu 1.5 return; 1465 salcianu 1.5 } 1466 salcianu 1.5 } 1467 salcianu 1.5 1468 salcianu 1.5 stop_no_def(q); 1469 salcianu 1.5 } 1470 salcianu 1.5 // SSI additions END 1471 salcianu 1.5 1472 salcianu 1.1.2.24 // catch the forgotten quads 1473 salcianu 1.1.2.24 public void visit(Quad q) { 1474 salcianu 1.5 assert false : "Unsupported Quad " + q; 1475 salcianu 1.1.2.24 } 1476 salcianu 1.1.2.24 1477 salcianu 1.1.2.24 // crash the system in the most spectacular way 1478 salcianu 1.1.2.24 private void stop_no_def(Quad q) { 1479 cananian 1.3.2.1 assert false : q + " doesn't define " + t; 1480 salcianu 1.1.2.24 } 1481 salcianu 1.1.2.24 1482 salcianu 1.1.2.24 // The Temp "tdep" is used in quad "q" to define "t" and 1483 salcianu 1.1.2.24 // can affect its type. This function qoes along the list 1484 salcianu 1.1.2.24 // of possible definitions for tdep and put the corresponding 1485 salcianu 1.1.2.24 // ExactTemp's in the array of dependencies for <t,q>. 1486 salcianu 1.1.2.24 private void add_deps(Temp tdep, Quad q) { 1487 salcianu 1.5 Set set = new HashSet(); 1488 salcianu 1.5 collect_deps(tdep, q, set); 1489 salcianu 1.5 deps = (ExactTemp[]) set.toArray(new ExactTemp[set.size()]); 1490 salcianu 1.5 } 1491 salcianu 1.5 1492 salcianu 1.5 private void add_deps(Temp src[], Quad q) { 1493 salcianu 1.5 Set set = new HashSet(); 1494 salcianu 1.5 for(int i = 0; i < src.length; i++) 1495 salcianu 1.5 collect_deps(src[i], q, set); 1496 salcianu 1.5 deps = (ExactTemp[]) set.toArray(new ExactTemp[set.size()]); 1497 salcianu 1.5 } 1498 salcianu 1.5 1499 salcianu 1.5 // collect into set the exact temps that flow into <tdep, q> 1500 salcianu 1.5 private void collect_deps(Temp tdep, Quad q, Set set) { 1501 salcianu 1.1.2.24 Set reaching_defs = rdef.reachingDefs(q, tdep); 1502 salcianu 1.5 1503 salcianu 1.5 assert 1504 salcianu 1.5 !reaching_defs.isEmpty() : 1505 salcianu 1.5 "Temp " + tdep + " in " + q + " has no reaching definition!"; 1506 salcianu 1.5 1507 cananian 1.12 for(Object qdefO : reaching_defs) { 1508 cananian 1.12 Quad qdef = (Quad) qdefO; 1509 salcianu 1.5 set.add(getExactTemp(tdep, qdef)); 1510 salcianu 1.1.2.1 } 1511 salcianu 1.1.2.24 } 1512 salcianu 1.5 1513 salcianu 1.5 1514 salcianu 1.1.2.24 }; 1515 salcianu 1.1.2.24 private QuadVisitorDD qvis_dd = new QuadVisitorDD(); 1516 salcianu 1.1.2.1 1517 salcianu 1.5 1518 salcianu 1.5 private void show_deps(ExactTemp et, ExactTemp deps[]) { 1519 salcianu 1.5 System.out.print("\nDeps for " + et.shortDescription() + " = { "); 1520 salcianu 1.5 for(int i = 0; (deps != null) && (i < deps.length); i++) 1521 salcianu 1.5 System.out.print(deps[i].shortDescription() + " "); 1522 salcianu 1.5 System.out.println(" } "); 1523 salcianu 1.5 } 1524 salcianu 1.5 1525 salcianu 1.5 1526 salcianu 1.1.2.1 // Returns all the ExactTemps whose types influence the type of the 1527 salcianu 1.1.2.1 // ExactType et. 1528 salcianu 1.1.2.24 private ExactTemp[] getDependencies(ExactTemp et, ReachingDefs rdef) { 1529 salcianu 1.1.2.24 qvis_dd.t = et.t; 1530 salcianu 1.1.2.24 qvis_dd.ud = et.ud; 1531 salcianu 1.1.2.24 qvis_dd.deps = null; 1532 salcianu 1.1.2.24 qvis_dd.rdef = rdef; 1533 salcianu 1.5 1534 salcianu 1.1.2.24 et.q.accept(qvis_dd); 1535 salcianu 1.5 1536 salcianu 1.1.2.24 if(qvis_dd.deps == null) 1537 salcianu 1.1.2.1 return (new ExactTemp[0]); 1538 salcianu 1.1.2.24 return qvis_dd.deps; 1539 salcianu 1.1.2.1 } 1540 salcianu 1.1.2.1 1541 salcianu 1.5 1542 salcianu 1.5 // Checks whether q corresponds to a typecast that defines t to be 1543 salcianu 1.5 // the restriction of some temp t2 to some class hclass. This means: 1544 salcianu 1.5 // 1. q has a single predecessor: tb = t2 INSTANCEOF hclass 1545 salcianu 1.5 // 2. q has the form CJMP tb 1546 salcianu 1.5 // 3. t is t2 variant on branch 1: < _ , t > = sigma(t2) 1547 salcianu 1.5 // If all these conditions are true, return hclass, o.w. return null 1548 salcianu 1.5 private static HClass is_typecast(CJMP q, Temp t) { 1549 salcianu 1.5 if(q.prevLength() == 1) { 1550 salcianu 1.5 Quad prev = q.prev(0); 1551 salcianu 1.5 if(prev instanceof INSTANCEOF) { 1552 salcianu 1.5 INSTANCEOF inst = (INSTANCEOF) prev; 1553 salcianu 1.6 Temp tb = inst.dst(); 1554 salcianu 1.6 if(tb.equals(q.test())) { 1555 salcianu 1.5 Temp tested = inst.src(); 1556 salcianu 1.5 int i = getSigmaForTemp(q, tested); 1557 salcianu 1.6 1558 salcianu 1.6 if(i == -1) return null; 1559 salcianu 1.6 1560 salcianu 1.5 Temp dst[] = q.dst(i); 1561 salcianu 1.5 if(t.equals(dst[1])) { 1562 salcianu 1.5 // this is actually a typecast ! 1563 salcianu 1.5 return inst.hclass(); 1564 salcianu 1.5 } 1565 salcianu 1.5 } 1566 salcianu 1.5 } 1567 salcianu 1.5 } 1568 salcianu 1.5 // not a typecast 1569 salcianu 1.5 return null; 1570 salcianu 1.5 } 1571 salcianu 1.5 1572 salcianu 1.7 1573 salcianu 1.7 // Checks whether t is defined as the restriction on the true 1574 salcianu 1.7 // branch of a test t2 == null (in that case t is null, ie type 1575 salcianu 1.7 // Void). 1576 salcianu 1.7 // 1577 salcianu 1.7 // Right way to do it: verify that all following cond hold: 1578 salcianu 1.7 // q = CJMP tb; SIGMA: < _ , t> = t2 1579 salcianu 1.7 // tb is defined by tb = OPER acmpeq(t2, t_null) 1580 salcianu 1.7 // t_null is defined by t_null = CONST null 1581 salcianu 1.7 // 1582 salcianu 1.7 // MIT hack: 1583 salcianu 1.7 // suppose they come in the order: CONST, OPER, SIGMA 1584 salcianu 1.7 // this way we don't need reaching defs here. 1585 salcianu 1.7 private static boolean is_nulltest(CJMP q, Temp t) { 1586 salcianu 1.7 if((q.prevLength() != 1) || 1587 salcianu 1.7 !(q.prev(0) instanceof OPER)) 1588 salcianu 1.7 return false; 1589 salcianu 1.7 OPER oper = (OPER) q.prev(0); 1590 salcianu 1.7 1591 salcianu 1.7 if(!oper.dst().equals(q.test()) || 1592 salcianu 1.7 (oper.opcode() != Qop.ACMPEQ)) 1593 salcianu 1.7 return false; 1594 salcianu 1.7 1595 salcianu 1.7 if((oper.prevLength() != 1) || 1596 salcianu 1.7 !(oper.prev(0) instanceof CONST)) 1597 salcianu 1.7 return false; 1598 salcianu 1.7 CONST con = (CONST) oper.prev(0); 1599 salcianu 1.7 1600 salcianu 1.7 if(con.type() != HClass.Void) 1601 salcianu 1.7 return false; 1602 salcianu 1.7 1603 salcianu 1.7 Temp t_null = con.dst(); 1604 salcianu 1.7 Temp t2 = null; 1605 salcianu 1.7 if(t_null.equals(oper.operands(0))) 1606 salcianu 1.7 t2 = oper.operands(1); 1607 salcianu 1.7 else if(t_null.equals(oper.operands(1))) 1608 salcianu 1.7 t2 = oper.operands(0); 1609 salcianu 1.7 else 1610 salcianu 1.7 return false; 1611 salcianu 1.7 1612 salcianu 1.7 int i = getSigmaForTemp(q, t2); 1613 salcianu 1.7 if(i == -1) return false; 1614 salcianu 1.7 1615 salcianu 1.7 return t.equals(q.dst(i)[1]); 1616 salcianu 1.7 } 1617 salcianu 1.7 1618 salcianu 1.7 1619 salcianu 1.5 // returns the index of the sigma function that has t_src as a 1620 salcianu 1.5 // source in the big SIGMA node q (with potentially many sigma 1621 salcianu 1.5 // functions) 1622 salcianu 1.5 private static int getSigmaForTemp(SIGMA q, Temp t_src) { 1623 salcianu 1.5 for(int i = 0; i < q.numSigmas(); i++) { 1624 salcianu 1.5 if(q.src(i).equals(t_src)) 1625 salcianu 1.5 return i; // we found it! 1626 salcianu 1.5 } 1627 salcianu 1.5 // t is not defined by this SIGMA 1628 salcianu 1.5 return -1; 1629 salcianu 1.5 } 1630 salcianu 1.5 1631 salcianu 1.1.2.1 ////// DEPENDENCY DETECTION (getDependencies) - END 1632 salcianu 1.1.2.1 1633 salcianu 1.1.2.24 1634 salcianu 1.1.2.1 // The following code is responsible for assuring that at most one 1635 salcianu 1.1.2.24 // ExactTemp object representing the temp t defined/used at quad q exists 1636 salcianu 1.1.2.1 // at the execution time. This is necessary since we keep the next and 1637 salcianu 1.1.2.1 // prev info *into* the ExactTemp structure and not in a map (for 1638 salcianu 1.1.2.1 // efficiency reasons), so all the info related to a conceptual ExactTemp 1639 salcianu 1.1.2.1 // must be in a single place. 1640 salcianu 1.1.2.24 // This is enforced by having a Map<ExactTempS,ExactTemp> that maps 1641 salcianu 1.1.2.24 // an ExactTempS (just a <t, q, ud> tuple) to the full ExactTemp object. 1642 salcianu 1.1.2.24 // When we need the ExactTemp for a given <t, q, ud> 1643 salcianu 1.1.2.24 // pair, we search <t, q, ud> in that map; if found we return the existent 1644 salcianu 1.1.2.1 // object, otherwise we create a new one and put it into the map. 1645 salcianu 1.1.2.1 // Of course, no part of the program should dirrectly allocate an 1646 salcianu 1.1.2.1 // ExactTemp, instead the "getExactTemp" function should be called. 1647 salcianu 1.1.2.24 private class ExactTempS { // S for short 1648 salcianu 1.1.2.1 Temp t; 1649 salcianu 1.1.2.1 Quad q; 1650 salcianu 1.1.2.24 int ud; 1651 salcianu 1.1.2.24 ExactTempS(Temp t, Quad q, int ud) { 1652 salcianu 1.1.2.24 this.t = t; 1653 salcianu 1.1.2.24 this.q = q; 1654 salcianu 1.1.2.24 this.ud = ud; 1655 salcianu 1.1.2.1 } 1656 salcianu 1.1.2.1 public int hashCode(){ 1657 salcianu 1.1.2.24 return t.hashCode() + q.hashCode() + ud; 1658 salcianu 1.1.2.1 } 1659 salcianu 1.1.2.1 public boolean equals(Object o){ 1660 salcianu 1.1.2.1 ExactTempS ets2 = (ExactTempS) o; 1661 salcianu 1.1.2.24 return 1662 salcianu 1.1.2.24 (this.t == ets2.t) && 1663 salcianu 1.1.2.24 (this.q == ets2.q) && 1664 salcianu 1.1.2.24 (this.ud == ets2.ud); 1665 salcianu 1.1.2.1 } 1666 salcianu 1.1.2.1 } 1667 salcianu 1.1.2.1 private Map ets2et = null; 1668 salcianu 1.1.2.24 private ExactTempS ets_test = new ExactTempS(null, null, ExactTemp.DEF); 1669 salcianu 1.1.2.24 private ExactTemp getExactTemp(Temp t, Quad q, int ud) { 1670 salcianu 1.1.2.24 ets_test.t = t; 1671 salcianu 1.1.2.24 ets_test.q = q; 1672 salcianu 1.1.2.24 ets_test.ud = ud; 1673 salcianu 1.1.2.1 ExactTemp et = (ExactTemp) ets2et.get(ets_test); 1674 salcianu 1.8 if(et == null) { 1675 salcianu 1.1.2.24 et = new ExactTemp(t, q, ud); 1676 salcianu 1.1.2.24 ExactTempS ets = new ExactTempS(t, q, ud); 1677 salcianu 1.1.2.24 ets2et.put(ets, et); 1678 salcianu 1.1.2.1 } 1679 salcianu 1.1.2.1 return et; 1680 salcianu 1.1.2.1 } 1681 salcianu 1.1.2.24 private ExactTemp getExactTemp(Temp t, Quad q) { 1682 salcianu 1.1.2.24 return getExactTemp(t, q, ExactTemp.DEF); 1683 salcianu 1.1.2.24 } 1684 salcianu 1.1.2.24 1685 salcianu 1.1.2.1 // the end of "unique ExactTemp" code. 1686 salcianu 1.1.2.1 1687 salcianu 1.1.2.1 1688 salcianu 1.13 // Computes the reverse topologically sorted list of strongly connected 1689 salcianu 1.1.2.1 // components containing the definitions of the "interesting" temps. 1690 salcianu 1.1.2.1 // The edges between this nodes models the relation 1691 salcianu 1.1.2.24 // "the type of ExactType x influences the type of the ExactType y" 1692 salcianu 1.14 private List<SCComponent> compute_sccs 1693 salcianu 1.13 (Set initial_set, ReachingDefs rdef) { 1694 salcianu 1.1.2.24 // 1. Compute the graph: ExactTemps, successors and predecessors. 1695 salcianu 1.5 // predecessors are put into the prev field of the ExactTemps; 1696 salcianu 1.1.2.24 // successors are not put into the ExactTemps, but into a separate 1697 salcianu 1.1.2.24 // relation - "next_rel" - as they are gradually discovered. 1698 salcianu 1.1.2.24 // ReachingDefs gives us the prev part. 1699 salcianu 1.1.2.24 Relation next_rel = new RelationImpl(); 1700 salcianu 1.1.2.1 Set already_visited = new HashSet(); 1701 salcianu 1.1.2.1 PAWorkList W = new PAWorkList(); 1702 salcianu 1.5 1703 salcianu 1.1.2.1 W.addAll(initial_set); 1704 salcianu 1.1.2.1 while(!W.isEmpty()){ 1705 salcianu 1.1.2.1 ExactTemp et = (ExactTemp) W.remove(); 1706 salcianu 1.1.2.1 already_visited.add(et); 1707 salcianu 1.1.2.1 1708 salcianu 1.1.2.24 et.prev = getDependencies(et, rdef); 1709 salcianu 1.1.2.3 1710 salcianu 1.1.2.24 for(int i = 0; i < et.prev.length; i++){ 1711 salcianu 1.1.2.24 ExactTemp et2 = (ExactTemp) et.prev[i]; 1712 salcianu 1.1.2.1 1713 salcianu 1.5 assert (et2 != null) : "Something wrong with " + et; 1714 salcianu 1.1.2.1 1715 salcianu 1.1.2.24 next_rel.add(et2, et); 1716 salcianu 1.1.2.1 if(!already_visited.contains(et2)) 1717 salcianu 1.1.2.1 W.add(et2); 1718 salcianu 1.1.2.1 } 1719 salcianu 1.1.2.1 } 1720 salcianu 1.1.2.1 1721 salcianu 1.1.2.1 // now, put the predecessors in the ExactTemps 1722 cananian 1.12 for(Object etO : next_rel.keys()) { 1723 cananian 1.12 ExactTemp et = (ExactTemp) etO; 1724 salcianu 1.1.2.24 Set next = next_rel.getValues(et); 1725 salcianu 1.1.2.24 et.next = (ExactTemp[]) next.toArray(new ExactTemp[next.size()]); 1726 salcianu 1.1.2.1 } 1727 salcianu 1.1.2.1 1728 salcianu 1.1.2.24 // 2. Build the component graph and sort it topollogically. 1729 salcianu 1.1.2.24 1730 salcianu 1.1.2.24 // Navigator into the graph of ExactTemps. prev returns the ExactTemps 1731 salcianu 1.1.2.24 // whose types influence the type of "node" ExactTemp; next returns 1732 salcianu 1.1.2.24 // the ExactTemps whose types are affected by the type of node. 1733 salcianu 1.11 Navigator et_navigator = new Navigator() { 1734 salcianu 1.11 public Object[] next(Object node){ 1735 salcianu 1.11 return ((ExactTemp) node).next; 1736 salcianu 1.11 } 1737 salcianu 1.11 public Object[] prev(Object node){ 1738 salcianu 1.11 return ((ExactTemp) node).prev; 1739 salcianu 1.11 } 1740 salcianu 1.11 }; 1741 salcianu 1.11 1742 salcianu 1.13 return 1743 salcianu 1.13 (new TopSortedCompDiGraph 1744 salcianu 1.13 (DiGraph.diGraph(already_visited, et_navigator))). 1745 salcianu 1.13 decrOrder(); 1746 salcianu 1.1.2.1 } 1747 salcianu 1.1.2.1 1748 salcianu 1.1.2.1 1749 salcianu 1.1.2.1 // Set the types of the parameters of the method underlying mm, using the 1750 salcianu 1.1.2.1 // appropriate type specializations. 1751 salcianu 1.1.2.1 private void set_parameter_types(MetaMethod mm, HCode hcode){ 1752 salcianu 1.1.2.1 METHOD m = (METHOD) ((HEADER) hcode.getRootElement()).next(1); 1753 salcianu 1.1.2.1 1754 salcianu 1.1.2.1 int nb_params = m.paramsLength(); 1755 salcianu 1.1.2.1 if(CAUTION && (nb_params != mm.nbParams())) 1756 cananian 1.3.2.1 assert false : "Wrong number of params in " + m; 1757 salcianu 1.1.2.1 1758 salcianu 1.1.2.1 for(int i = 0; i < nb_params ; i++) 1759 salcianu 1.1.2.24 getExactTemp(m.params(i), m).addType(mm.getType(i)); 1760 salcianu 1.1.2.1 } 1761 salcianu 1.1.2.1 1762 salcianu 1.1.2.1 1763 salcianu 1.1.2.1 // computes the types of the interesting ExactTemps, starting 1764 salcianu 1.1.2.1 // with those in the strongly connected component "scc". 1765 salcianu 1.14 private void compute_types(List<SCComponent> sccs) { 1766 salcianu 1.13 try { 1767 salcianu 1.14 for(SCComponent scc : sccs) 1768 salcianu 1.14 process_scc(scc); 1769 salcianu 1.7 } 1770 salcianu 1.7 catch(AssertionError e) { 1771 salcianu 1.7 display_mm_data(mm_work); 1772 salcianu 1.7 throw e; 1773 salcianu 1.7 } 1774 salcianu 1.1.2.1 } 1775 salcianu 1.1.2.1 1776 salcianu 1.1.2.1 // TYPE INFERENCE QUAD VISITOR - BEGIN 1777 salcianu 1.1.2.1 1778 salcianu 1.1.2.24 private class QuadVisitorTI extends QuadVisitor { 1779 salcianu 1.1.2.1 1780 salcianu 1.1.2.24 Temp t = null; 1781 salcianu 1.1.2.24 ExactTemp et = null; 1782 salcianu 1.1.2.23 1783 salcianu 1.1.2.24 public void visit(MOVE q) { 1784 salcianu 1.1.2.23 if(CAUTION && !t.equals(q.dst())) 1785 salcianu 1.1.2.23 stop_no_def(q); 1786 salcianu 1.5 treat_move_use(); 1787 salcianu 1.1.2.23 } 1788 salcianu 1.5 1789 salcianu 1.1.2.24 public void visit(GET q) { 1790 salcianu 1.1.2.23 if(CAUTION && !t.equals(q.dst())) 1791 salcianu 1.1.2.23 stop_no_def(q); 1792 salcianu 1.1.2.24 et.addType(new GenType(q.field().getType(), GenType.POLY)); 1793 salcianu 1.1.2.23 } 1794 salcianu 1.1.2.24 1795 salcianu 1.1.2.24 public void visit(AGET q) { 1796 salcianu 1.1.2.23 if(CAUTION && !t.equals(q.dst())) 1797 salcianu 1.1.2.23 stop_no_def(q); 1798 salcianu 1.1.2.1 1799 salcianu 1.1.2.23 // For all the possible types for the source array, take 1800 salcianu 1.1.2.23 // the type of the component 1801 salcianu 1.1.2.24 for(int i = 0; i < et.prev.length; i++) { 1802 salcianu 1.1.2.24 ExactTemp eta = et.prev[i]; 1803 salcianu 1.1.2.24 for(Iterator it_types = eta.getTypes(); it_types.hasNext(); ) { 1804 salcianu 1.1.2.24 HClass c = ((GenType) it_types.next()).getHClass(); 1805 salcianu 1.7 if(c.equals(HClass.Void)) { 1806 salcianu 1.1.2.23 et.addType(new GenType(HClass.Void, GenType.MONO)); 1807 salcianu 1.7 // commented it: I think continue is the right attitude! 1808 salcianu 1.7 // NO! 1809 salcianu 1.7 // continue; 1810 salcianu 1.7 } 1811 salcianu 1.1.2.24 else { 1812 salcianu 1.1.2.23 HClass hcomp = c.getComponentType(); 1813 salcianu 1.5 assert 1814 salcianu 1.5 hcomp != null : 1815 salcianu 1.7 "\n" + q.objectref() + 1816 salcianu 1.7 " could have the non-array type <" + c + "> in " + 1817 salcianu 1.10 Util.code2str(q); 1818 salcianu 1.1.2.24 et.addType(new GenType(hcomp, GenType.POLY)); 1819 salcianu 1.1.2.1 } 1820 salcianu 1.1.2.1 } 1821 salcianu 1.1.2.1 } 1822 salcianu 1.1.2.23 } 1823 salcianu 1.1.2.23 1824 salcianu 1.1.2.24 public void visit(CALL q) { 1825 salcianu 1.1.2.24 if(et.ud == ExactTemp.DEF) { 1826 salcianu 1.1.2.24 if(t.equals(q.retval())) { 1827 salcianu 1.1.2.24 et.addType(new GenType(q.method().getReturnType(), 1828 salcianu 1.1.2.24 GenType.POLY)); 1829 salcianu 1.1.2.24 return; 1830 salcianu 1.1.2.24 } 1831 salcianu 1.1.2.24 if(t.equals(q.retex())) { 1832 salcianu 1.1.2.24 HClass[] excp = q.method().getExceptionTypes(); 1833 salcianu 1.1.2.24 for(int i = 0; i < excp.length; i++) 1834 salcianu 1.5 et.addType(new GenType(excp[i], GenType.POLY)); 1835 salcianu 1.1.2.24 // According to the JLS, exceptions that are subclasses of 1836 salcianu 1.1.2.24 // java.lang.RuntimeException and java.lang.Error need 1837 salcianu 1.1.2.24 // not be explicitly declared; they can be thrown by any 1838 salcianu 1.1.2.24 // method. 1839 salcianu 1.1.2.24 et.addType(new GenType(jl_RuntimeException, GenType.POLY)); 1840 salcianu 1.1.2.24 et.addType(new GenType(jl_Error, GenType.POLY)); 1841 salcianu 1.1.2.24 return; 1842 salcianu 1.1.2.24 } 1843 salcianu 1.5 1844 salcianu 1.5 visit((SIGMA) q); 1845 salcianu 1.1.2.1 } 1846 salcianu 1.5 else // it's a USE; we just have to merge the reaching defs 1847 salcianu 1.5 treat_move_use(); 1848 salcianu 1.1.2.23 } 1849 salcianu 1.1.2.23 1850 salcianu 1.1.2.24 public void visit(NEW q) { 1851 salcianu 1.1.2.23 if(CAUTION && !t.equals(q.dst())) 1852 salcianu 1.1.2.23 stop_no_def(q); 1853 salcianu 1.1.2.23 et.addType(new GenType(q.hclass(),GenType.MONO)); 1854 salcianu 1.1.2.23 } 1855 salcianu 1.1.2.23 1856 salcianu 1.1.2.24 public void visit(ANEW q) { 1857 salcianu 1.1.2.23 if(CAUTION && !t.equals(q.dst())) 1858 salcianu 1.1.2.23 stop_no_def(q); 1859 salcianu 1.1.2.23 et.addType(new GenType(q.hclass(),GenType.MONO)); 1860 salcianu 1.1.2.23 } 1861 salcianu 1.1.2.1 1862 salcianu 1.1.2.24 public void visit(TYPECAST q) { 1863 salcianu 1.1.2.23 if(CAUTION && !t.equals(q.objectref())) 1864 salcianu 1.1.2.23 stop_no_def(q); 1865 salcianu 1.1.2.23 et.addType(new GenType(q.hclass(), GenType.POLY)); 1866 salcianu 1.1.2.23 } 1867 salcianu 1.1.2.23 1868 salcianu 1.1.2.24 public void visit(METHOD q) { 1869 salcianu 1.1.2.23 // do nothing; the types of the parameters have been 1870 salcianu 1.1.2.23 // already set by set_parameter_types. 1871 salcianu 1.1.2.24 if(CAUTION) { 1872 salcianu 1.1.2.23 boolean found = false; 1873 salcianu 1.1.2.23 for(int i = 0; i < q.paramsLength(); i++) 1874 salcianu 1.1.2.23 if(q.params(i).equals(t)){ 1875 salcianu 1.1.2.23 found = true; 1876 salcianu 1.1.2.23 break; 1877 salcianu 1.1.2.23 } 1878 salcianu 1.1.2.23 if(!found) stop_no_def(q); 1879 salcianu 1.1.2.1 } 1880 salcianu 1.1.2.23 } 1881 salcianu 1.1.2.23 1882 salcianu 1.1.2.24 public void visit(CONST q) { 1883 salcianu 1.1.2.24 if(CAUTION) { 1884 salcianu 1.1.2.23 if(!t.equals(q.dst())) stop_no_def(q); 1885 salcianu 1.1.2.1 } 1886 salcianu 1.1.2.23 et.addType(new GenType(q.type(), GenType.MONO)); 1887 salcianu 1.1.2.23 } 1888 salcianu 1.5 1889 salcianu 1.5 // SSI additions BEGIN 1890 salcianu 1.5 public void visit(PHI q) { 1891 salcianu 1.5 treat_move_use(); 1892 salcianu 1.5 } 1893 salcianu 1.5 1894 salcianu 1.5 // recognize the translation of a TYPECAST in QuadSSI: 1895 salcianu 1.5 // a CJMP t2 preceded by a t2 = t INSTANCEOF hclass 1896 salcianu 1.5 public void visit(CJMP q) { 1897 salcianu 1.7 HClass hclass = null; 1898 salcianu 1.7 if(ssx_form && ((hclass = is_typecast(q, t)) != null)) { 1899 salcianu 1.5 et.addType(new GenType(hclass, GenType.POLY)); 1900 salcianu 1.7 } 1901 salcianu 1.7 else if(is_nulltest(q, t)) { 1902 salcianu 1.7 // t is t2's restriction on the true branch of a 1903 salcianu 1.7 // t2 != null test -> it is always null 1904 salcianu 1.7 et.addType(new GenType(HClass.Void, GenType.MONO)); 1905 salcianu 1.7 } 1906 salcianu 1.5 else 1907 salcianu 1.5 visit((SIGMA) q); 1908 salcianu 1.5 } 1909 salcianu 1.5 1910 salcianu 1.5 public void visit(SIGMA q) { 1911 salcianu 1.5 treat_move_use(); 1912 salcianu 1.5 } 1913 salcianu 1.5 // SSI additions END 1914 salcianu 1.5 1915 salcianu 1.5 // treat MOVE-like instructions 1916 salcianu 1.5 private void treat_move_use() { 1917 salcianu 1.5 for(int i = 0; i < et.prev.length; i++) 1918 salcianu 1.5 et.addTypes(et.prev[i].getTypeSet()); 1919 salcianu 1.5 } 1920 salcianu 1.7 1921 salcianu 1.1.2.24 public void visit(Quad q) { 1922 cananian 1.3.2.1 assert false : "Unsupported Quad " + q; 1923 salcianu 1.1.2.23 } 1924 salcianu 1.1.2.23 1925 salcianu 1.1.2.24 private void stop_no_def(Quad q) { 1926 cananian 1.3.2.1 assert false : q + " doesn't define " + t; 1927 salcianu 1.1.2.23 } 1928 salcianu 1.1.2.23 1929 salcianu 1.1.2.23 }; 1930 salcianu 1.1.2.24 private QuadVisitorTI qvis_ti = new QuadVisitorTI(); 1931 salcianu 1.1.2.23 1932 salcianu 1.1.2.1 // TYPE INFERENCE QUAD VISITOR - END 1933 salcianu 1.1.2.1 1934 salcianu 1.1.2.1 1935 salcianu 1.1.2.24 private void process_scc(SCComponent scc) { 1936 salcianu 1.1.2.1 final PAWorkList W = new PAWorkList(); 1937 salcianu 1.1.2.1 1938 salcianu 1.1.2.1 if(DEBUG) 1939 salcianu 1.7 System.out.println("\n\nProcessing " + scc); 1940 salcianu 1.1.2.1 1941 salcianu 1.15 W.addAll(scc.nodes()); 1942 salcianu 1.5 while(!W.isEmpty()) { 1943 salcianu 1.1.2.1 ExactTemp et = (ExactTemp) W.remove(); 1944 salcianu 1.1.2.1 1945 salcianu 1.1.2.24 // This inelegant modality of passing parameters to the 1946 salcianu 1.1.2.24 // type inference quad visitor is motivated by our struggle to 1947 salcianu 1.1.2.24 // create a single QuadVisitorTI object. 1948 salcianu 1.1.2.24 qvis_ti.t = et.t; 1949 salcianu 1.1.2.24 qvis_ti.et = et; 1950 salcianu 1.1.2.1 1951 salcianu 1.1.2.1 Set old_gen_type = new HashSet(et.getTypeSet()); 1952 salcianu 1.1.2.24 et.q.accept(qvis_ti); 1953 salcianu 1.1.2.1 Set new_gen_type = et.getTypeSet(); 1954 salcianu 1.1.2.1 1955 salcianu 1.1.2.1 if(!new_gen_type.equals(old_gen_type)) 1956 salcianu 1.1.2.24 for(int i = 0; i < et.next.length; i++){ 1957 salcianu 1.1.2.24 ExactTemp et2 = et.next[i]; 1958 salcianu 1.1.2.24 if(scc.contains(et2)) W.add(et2); 1959 salcianu 1.1.2.1 } 1960 salcianu 1.1.2.1 } 1961 salcianu 1.1.2.1 1962 salcianu 1.1.2.1 if(DEBUG) 1963 salcianu 1.15 for(Object etO : scc.nodes()){ 1964 cananian 1.12 ExactTemp et = (ExactTemp) etO; 1965 salcianu 1.7 System.out.println("\n##:< " + et.shortDescription() + 1966 salcianu 1.7 " -> " + et.getTypeSet() + " >\n"); 1967 salcianu 1.1.2.1 } 1968 salcianu 1.1.2.1 } 1969 salcianu 1.1.2.1 1970 salcianu 1.1.2.24 1971 salcianu 1.1.2.24 private static long time() { 1972 salcianu 1.1.2.24 return System.currentTimeMillis(); 1973 salcianu 1.1.2.24 } 1974 salcianu 1.1.2.1 } 1975 cananian 1.2