1 salcianu 1.1 // IAStatistics.java, created Tue Apr 23 19:00:41 2002 by salcianu 2 salcianu 1.1 // Copyright (C) 2000 Alexandru Salcianu <salcianu@MIT.EDU> 3 salcianu 1.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 salcianu 1.1 package harpoon.Analysis.MemOpt; 5 salcianu 1.1 6 salcianu 1.1 import java.util.Set; 7 salcianu 1.2 import java.util.HashSet; 8 salcianu 1.1 import java.util.Iterator; 9 salcianu 1.1 import java.util.Map; 10 salcianu 1.1 import java.util.HashMap; 11 salcianu 1.1 import java.util.Arrays; 12 salcianu 1.1 import java.util.Collection; 13 salcianu 1.1 14 salcianu 1.1 import java.lang.Comparable; 15 salcianu 1.1 16 salcianu 1.1 import java.io.ObjectInputStream; 17 salcianu 1.1 import java.io.FileInputStream; 18 salcianu 1.1 import java.io.FileReader; 19 salcianu 1.1 import java.io.BufferedReader; 20 salcianu 1.1 21 salcianu 1.1 import gnu.getopt.Getopt; 22 salcianu 1.1 23 salcianu 1.1 import harpoon.ClassFile.Linker; 24 salcianu 1.1 import harpoon.ClassFile.HMethod; 25 salcianu 1.1 import harpoon.ClassFile.HClass; 26 salcianu 1.1 import harpoon.ClassFile.HCode; 27 salcianu 1.1 import harpoon.ClassFile.HCodeFactory; 28 salcianu 1.1 import harpoon.ClassFile.CachingCodeFactory; 29 salcianu 1.1 import harpoon.ClassFile.SerializableCodeFactory; 30 salcianu 1.1 31 salcianu 1.4 import harpoon.Backend.Generic.Frame; 32 salcianu 1.4 33 salcianu 1.9 import harpoon.Util.Timer; 34 salcianu 1.2 import harpoon.Util.Util; 35 salcianu 1.2 36 salcianu 1.1 import harpoon.Analysis.ClassHierarchy; 37 salcianu 1.1 import harpoon.Analysis.Quads.QuadClassHierarchy; 38 salcianu 1.1 import harpoon.Analysis.MetaMethods.SmartCallGraph; 39 salcianu 1.1 import harpoon.Analysis.MetaMethods.MetaCallGraphImpl; 40 salcianu 1.1 import harpoon.Analysis.Quads.CallGraph; 41 salcianu 1.6 import harpoon.Instrumentation.AllocationStatistics.AllocationStatistics; 42 salcianu 1.1 43 salcianu 1.1 import harpoon.Analysis.MemOpt.IncompatibilityAnalysis; 44 salcianu 1.1 45 salcianu 1.1 import harpoon.IR.Quads.Quad; 46 salcianu 1.2 import harpoon.IR.Quads.QuadVisitor; 47 salcianu 1.3 import harpoon.IR.Quads.QuadWithTry; 48 salcianu 1.1 import harpoon.IR.Quads.QuadNoSSA; 49 salcianu 1.1 import harpoon.IR.Quads.QuadSSI; 50 salcianu 1.1 import harpoon.IR.Quads.NEW; 51 salcianu 1.1 import harpoon.IR.Quads.ANEW; 52 salcianu 1.1 53 salcianu 1.1 /** 54 salcianu 1.1 * <code>IAStatistics</code> 55 salcianu 1.1 * 56 salcianu 1.1 * @author Alexandru Salcianu <salcianu@MIT.EDU> 57 cananian 1.13 * @version $Id: IAStatistics.java,v 1.13 2004/02/08 03:19:53 cananian Exp $ 58 salcianu 1.1 */ 59 salcianu 1.1 public abstract class IAStatistics { 60 salcianu 1.1 61 salcianu 1.3 private static class TypeStat implements Comparable, Cloneable { 62 salcianu 1.3 public HClass hclass; 63 salcianu 1.7 public long[][] count = new long[3][2]; 64 salcianu 1.1 65 salcianu 1.3 public TypeStat(HClass hclass) { this.hclass = hclass; } 66 salcianu 1.1 67 salcianu 1.1 public String toString() { 68 salcianu 1.1 return 69 salcianu 1.2 count[SITE][PREALLOC] + "\t" + count[SITE][HEAP] + "\t| " + 70 salcianu 1.7 count[OBJECT][PREALLOC] + "\t" + count[OBJECT][HEAP] + "\t| " + 71 salcianu 1.9 Util.memSizeFormat(count[SPACE][PREALLOC]) + 72 salcianu 1.8 "\t" + 73 salcianu 1.9 Util.memSizeFormat(count[SPACE][HEAP]) + 74 salcianu 1.2 "\t|| " + (hclass != null ? hclass.toString() : ""); 75 salcianu 1.2 } 76 salcianu 1.2 77 salcianu 1.2 public long totalAlloc(int kind) { 78 salcianu 1.2 return count[kind][HEAP] + count[kind][PREALLOC]; 79 salcianu 1.2 } 80 salcianu 1.2 81 salcianu 1.2 public int compareTo(Object o) { 82 salcianu 1.2 if(! (o instanceof TypeStat)) return -1; 83 salcianu 1.2 TypeStat ts2 = (TypeStat) o; 84 salcianu 1.2 return 85 salcianu 1.2 new Long(totalAlloc(OBJECT)) 86 salcianu 1.2 .compareTo(new Long(ts2.totalAlloc(OBJECT))); 87 salcianu 1.1 } 88 salcianu 1.3 89 salcianu 1.3 public TypeStat add(TypeStat ts) { 90 salcianu 1.7 for(int i = 0; i < 3; i++) 91 salcianu 1.3 for(int j = 0; j < 2; j++) 92 salcianu 1.3 this.count[i][j] += ts.count[i][j]; 93 salcianu 1.3 return this; 94 salcianu 1.3 } 95 salcianu 1.3 96 salcianu 1.3 public TypeStat diff(TypeStat ts) { 97 salcianu 1.7 for(int i = 0; i < 3; i++) 98 salcianu 1.3 for(int j = 0; j < 2; j++) 99 salcianu 1.3 this.count[i][j] -= ts.count[i][j]; 100 salcianu 1.3 return this; 101 salcianu 1.3 } 102 salcianu 1.3 103 salcianu 1.3 public Object clone() { 104 salcianu 1.3 try { 105 salcianu 1.3 TypeStat copy = (TypeStat) super.clone(); 106 salcianu 1.7 copy.count = new long[3][2]; 107 salcianu 1.7 for(int i = 0; i < 3; i++) 108 salcianu 1.3 for(int j = 0; j < 2; j++) 109 salcianu 1.3 copy.count[i][j] = this.count[i][j]; 110 salcianu 1.3 return copy; 111 salcianu 1.3 } 112 salcianu 1.3 catch(CloneNotSupportedException e) { 113 salcianu 1.3 e.printStackTrace(); 114 salcianu 1.3 System.exit(1); 115 salcianu 1.3 return null; // never executed; makes compiler happy 116 salcianu 1.3 } 117 salcianu 1.3 } 118 salcianu 1.3 119 salcianu 1.3 public static TypeStat diff(TypeStat a, TypeStat b) { 120 salcianu 1.3 return ((TypeStat) a.clone()).diff(b); 121 salcianu 1.3 } 122 salcianu 1.1 } 123 salcianu 1.1 124 salcianu 1.1 private static final int SITE = 0; 125 salcianu 1.1 private static final int OBJECT = 1; 126 salcianu 1.7 private static final int SPACE = 2; 127 salcianu 1.1 private static final int HEAP = 0; 128 salcianu 1.1 private static final int PREALLOC = 1; 129 salcianu 1.1 130 salcianu 1.2 131 salcianu 1.2 /** Prints static and dynamic statisticis about the memory 132 salcianu 1.2 preallocation optimization through incompatibility analysis. 133 salcianu 1.2 134 salcianu 1.2 @param ia incompatibility analysis object that tells whether an 135 salcianu 1.2 allocation site is unitary (ie, can be preallocated) or not 136 salcianu 1.2 137 salcianu 1.2 @param as allocation statistics object that provides the 138 salcianu 1.2 dynamic data: how many times each allocation site was 139 salcianu 1.2 executed 140 salcianu 1.2 141 salcianu 1.4 @param hcf_nossa factory used to produce the SSI factory used 142 salcianu 1.4 by the <code>IncompatibilityAnalysis</code> <code>ia</code>. 143 salcianu 1.4 144 salcianu 1.4 @param linker Linker to get the classes 145 salcianu 1.4 146 salcianu 1.4 @param frame Frame used by the back-end. Useful for computing 147 salcianu 1.4 the size of the objects at runtime. 148 salcianu 1.4 */ 149 salcianu 1.1 public static void printStatistics(IncompatibilityAnalysis ia, 150 salcianu 1.1 AllocationStatistics as, 151 salcianu 1.3 HCodeFactory hcf_nossa, 152 salcianu 1.4 Linker linker, 153 salcianu 1.4 Frame frame) { 154 salcianu 1.3 155 salcianu 1.4 if(frame != null) 156 salcianu 1.4 ia.printStatistics(frame, linker); 157 salcianu 1.3 158 salcianu 1.4 Set analyzedMethods = new HashSet(ia.allMethods()); 159 salcianu 1.3 160 salcianu 1.4 // stats on the time required by the NoSSA -> SSI conversion 161 salcianu 1.4 ssiConversionStatistics(analyzedMethods, hcf_nossa); 162 salcianu 1.4 // stats on NEWs introduced for exception explicit handling 163 salcianu 1.4 withTry2NoSSAConversionStatistics(analyzedMethods, hcf_nossa); 164 salcianu 1.1 165 salcianu 1.4 Collection allocs = 166 salcianu 1.4 AllocationStatistics.getAllocs(analyzedMethods, hcf_nossa); 167 salcianu 1.1 168 salcianu 1.4 // stats on most executed allocation sites 169 salcianu 1.2 as.printStatistics(allocs, new MyVisitor(ia)); 170 salcianu 1.2 171 salcianu 1.4 TypeStat[] tss = buildStatistics(ia, as, allocs); 172 salcianu 1.4 173 salcianu 1.4 HClass hThrowable = linker.forName("java.lang.Throwable"); 174 salcianu 1.10 HClass hStringBuffer = linker.forName("java.lang.StringBuffer"); 175 salcianu 1.2 TypeStat total = new TypeStat(null); 176 salcianu 1.3 TypeStat total_arrays = new TypeStat(null); 177 salcianu 1.3 TypeStat total_throwables = new TypeStat(null); 178 salcianu 1.10 TypeStat total_sb = new TypeStat(null); 179 salcianu 1.4 TypeStat total_program = new TypeStat(null); 180 salcianu 1.2 181 salcianu 1.8 System.out.println 182 salcianu 1.8 ("SITES\t\t|OBJECTS\t|SPACE\t\t||"); 183 salcianu 1.8 System.out.println 184 salcianu 1.8 ("PREALLOC HEAP\t|PREALLOC HEAP\t|PREALLOC HEAP\t||CLASS"); 185 salcianu 1.2 System.out.println 186 salcianu 1.2 ("------------------------------------------------------------"); 187 salcianu 1.2 for(int index_ts = 0; index_ts < tss.length; index_ts++) { 188 salcianu 1.2 TypeStat ts = tss[index_ts]; 189 salcianu 1.2 System.out.println(ts); 190 salcianu 1.3 total.add(ts); 191 salcianu 1.3 if(ts.hclass.isArray()) 192 salcianu 1.3 total_arrays.add(ts); 193 salcianu 1.3 if(ts.hclass.isInstanceOf(hThrowable)) 194 salcianu 1.3 total_throwables.add(ts); 195 salcianu 1.10 if(ts.hclass.isInstanceOf(hStringBuffer)) 196 salcianu 1.10 total_sb.add(ts); 197 salcianu 1.1 } 198 salcianu 1.1 199 salcianu 1.2 System.out.println 200 salcianu 1.2 ("------------------------------------------------------------"); 201 salcianu 1.2 System.out.println(total); 202 salcianu 1.2 203 salcianu 1.3 printTotal("OVERALL", total); 204 salcianu 1.3 printTotal("ARRAYS", total_arrays); 205 salcianu 1.3 printTotal("NON-ARRAYS", TypeStat.diff(total, total_arrays)); 206 salcianu 1.3 printTotal("THROWABLES", total_throwables); 207 salcianu 1.3 printTotal("NON_THROWABLES", TypeStat.diff(total, total_throwables)); 208 salcianu 1.10 printTotal("STRINGBUFFERS", total_sb); 209 salcianu 1.4 } 210 salcianu 1.4 211 salcianu 1.4 212 salcianu 1.4 // prints statistics on how many allocation sites were introduced 213 salcianu 1.4 // by the QuadWithTry -> QuadNoSSA conversion (quite MANY!) 214 salcianu 1.4 private static void withTry2NoSSAConversionStatistics 215 salcianu 1.4 (Set methods, HCodeFactory hcf_nossa) { 216 salcianu 1.4 Collection allocs = AllocationStatistics.getAllocs(methods, hcf_nossa); 217 salcianu 1.4 Collection initial_allocs = 218 salcianu 1.4 AllocationStatistics.getAllocs(methods, QuadWithTry.codeFactory()); 219 salcianu 1.4 220 salcianu 1.4 long delta_sites = allocs.size() - initial_allocs.size(); 221 salcianu 1.4 222 salcianu 1.4 System.out.println 223 salcianu 1.9 (Util.longProportion(delta_sites, initial_allocs.size(), 5, 2) + 224 salcianu 1.4 " allocations introduced by QuadWithTry -> QuadNoSSA"); 225 salcianu 1.3 } 226 salcianu 1.3 227 salcianu 1.3 228 salcianu 1.3 private static void printTotal(String label, TypeStat total) { 229 salcianu 1.1 System.out.println 230 salcianu 1.4 (label + " PREALLOCATED SITES:\t" + 231 salcianu 1.9 Util.longProportion(total.count[SITE][PREALLOC], 232 salcianu 1.9 total.count[SITE][HEAP], 5, 2)); 233 salcianu 1.1 System.out.println 234 salcianu 1.4 (label + " PREALLOCATED OBJECTS:\t" + 235 salcianu 1.9 Util.longProportion(total.count[OBJECT][PREALLOC], 236 salcianu 1.9 total.count[OBJECT][HEAP], 5, 2)); 237 salcianu 1.7 System.out.println 238 salcianu 1.7 (label + " PREALLOCATED SPACE:\t" + 239 salcianu 1.10 Util.longProportion(total.count[SPACE][PREALLOC], 240 salcianu 1.10 total.count[SPACE][HEAP], 5, 2)); 241 salcianu 1.10 System.out.println 242 salcianu 1.10 (label + " Preallocated Space:\t" + 243 salcianu 1.9 Util.longProportion(total.count[SPACE][PREALLOC], 244 salcianu 1.9 total.count[SPACE][HEAP], 5, 2, true)); 245 salcianu 1.2 } 246 salcianu 1.2 247 salcianu 1.2 248 salcianu 1.2 private static class MyVisitor extends QuadVisitor { 249 salcianu 1.2 public MyVisitor(IncompatibilityAnalysis ia) { this.ia = ia; } 250 salcianu 1.2 251 salcianu 1.2 private IncompatibilityAnalysis ia; 252 salcianu 1.2 253 salcianu 1.2 public void visit(Quad quad) { 254 salcianu 1.2 System.out.println 255 salcianu 1.2 (selfIncompatible(quad, ia) ? "\tnon-unitary" : "\tunitary"); 256 salcianu 1.2 } 257 salcianu 1.1 } 258 salcianu 1.1 259 salcianu 1.1 260 salcianu 1.4 private static TypeStat get_type_stat(Map hclass2stat, HClass hclass) { 261 salcianu 1.4 TypeStat result = (TypeStat) hclass2stat.get(hclass); 262 salcianu 1.4 if(result == null) 263 salcianu 1.4 hclass2stat.put(hclass, result = new TypeStat(hclass)); 264 salcianu 1.4 return result; 265 salcianu 1.4 } 266 salcianu 1.2 267 salcianu 1.4 private static TypeStat[] buildStatistics 268 salcianu 1.4 (IncompatibilityAnalysis ia, AllocationStatistics as, 269 salcianu 1.4 Collection allocs) { 270 salcianu 1.4 Map hclass2stat = new HashMap(); 271 salcianu 1.4 272 cananian 1.13 for(Object qO : allocs) { 273 cananian 1.13 Quad q = (Quad) qO; 274 salcianu 1.4 275 salcianu 1.4 /* 276 salcianu 1.1 HMethod hm = q.getFactory().getMethod(); 277 salcianu 1.1 278 salcianu 1.4 // methods called only by the startup code are not analyzed; 279 salcianu 1.4 // (they are not transitively called from the entry method) 280 salcianu 1.4 // hence, we ignore all the allocation sites from there 281 salcianu 1.4 if(!ia.allMethods().contains(hm)) 282 salcianu 1.1 continue; 283 salcianu 1.3 */ 284 salcianu 1.1 285 salcianu 1.4 TypeStat ts = get_type_stat(hclass2stat, allocatedClass(q)); 286 salcianu 1.8 int place = 287 salcianu 1.12 (selfIncompatible(q, ia) || 288 salcianu 1.12 !PreallocOpt.extraCond(q) || 289 salcianu 1.12 PreallocOpt.hasFinalizer(q)) ? 290 salcianu 1.8 HEAP : PREALLOC; 291 salcianu 1.8 ts.count[OBJECT][place] += as.getCount(q); 292 salcianu 1.8 ts.count[SITE][place]++; 293 salcianu 1.8 ts.count[SPACE][place] += as.getMemAmount(q); 294 salcianu 1.1 } 295 salcianu 1.2 296 salcianu 1.4 Collection tss_coll = hclass2stat.values(); 297 salcianu 1.4 TypeStat[] tss = 298 salcianu 1.4 (TypeStat[]) tss_coll.toArray(new TypeStat[tss_coll.size()]); 299 salcianu 1.4 Arrays.sort(tss); 300 salcianu 1.4 301 salcianu 1.4 return tss; 302 salcianu 1.1 } 303 salcianu 1.1 304 salcianu 1.1 private static HClass allocatedClass(Quad q) { 305 salcianu 1.1 if(q instanceof NEW) 306 salcianu 1.1 return ((NEW) q).hclass(); 307 salcianu 1.1 else if(q instanceof ANEW) 308 salcianu 1.1 return ((ANEW) q).hclass(); 309 salcianu 1.1 else throw new IllegalArgumentException 310 salcianu 1.9 ("Not an allocation " + Util.code2str(q)); 311 salcianu 1.1 } 312 salcianu 1.1 313 salcianu 1.1 private static boolean selfIncompatible 314 salcianu 1.1 (Quad q, IncompatibilityAnalysis ia) { 315 salcianu 1.1 if(q instanceof ANEW) return true; 316 salcianu 1.2 assert q instanceof NEW; 317 salcianu 1.1 Quad qssi = ia.getSSIQuad(q); 318 salcianu 1.1 assert qssi != null : "null qssi"; 319 salcianu 1.4 return 320 salcianu 1.4 ia.isSelfIncompatible(qssi); 321 salcianu 1.4 } 322 salcianu 1.4 323 salcianu 1.4 324 salcianu 1.4 // prints statistics regarding the noSSA -> SSI conversion time 325 salcianu 1.4 // for the set of analyzed methods (not all methods; we want to 326 salcianu 1.4 // compare it with the analysis time) 327 salcianu 1.4 private static void ssiConversionStatistics(Collection methods, 328 salcianu 1.4 HCodeFactory hcf_nossa) { 329 salcianu 1.4 Timer timer = new Timer(); 330 salcianu 1.4 timer.start(); 331 salcianu 1.4 HCodeFactory hcf_ssi = QuadSSI.codeFactory(hcf_nossa); 332 salcianu 1.4 for(Iterator it = methods.iterator(); it.hasNext(); ) 333 salcianu 1.4 hcf_ssi.convert((HMethod) it.next()); 334 salcianu 1.4 timer.stop(); 335 salcianu 1.4 System.out.println("SSI conversion time: " + timer); 336 salcianu 1.1 } 337 salcianu 1.1 }