1 cananian 1.1.2.6 // InstrumentSyncOps.java, created Thu Jul 13 2:18:26 2000 by jwhaley 2 cananian 1.1.2.2 // Copyright (C) 2000 John Whaley <jwhaley@alum.mit.edu> 3 cananian 1.1.2.2 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.2.2 5 cananian 1.1.2.2 package harpoon.Analysis.PointerAnalysis; 6 cananian 1.1.2.2 7 cananian 1.1.2.2 import harpoon.ClassFile.HCode; 8 cananian 1.1.2.2 import harpoon.ClassFile.HMethod; 9 cananian 1.1.2.2 import harpoon.Analysis.MetaMethods.MetaMethod; 10 cananian 1.1.2.2 import harpoon.ClassFile.HClass; 11 cananian 1.1.2.2 import harpoon.ClassFile.Linker; 12 cananian 1.1.2.2 import harpoon.ClassFile.Loader; 13 cananian 1.1.2.2 import harpoon.ClassFile.HCodeElement; 14 cananian 1.1.2.2 import harpoon.ClassFile.HCodeFactory; 15 cananian 1.1.2.2 import harpoon.IR.Quads.Quad; 16 cananian 1.1.2.2 import harpoon.IR.Quads.QuadVisitor; 17 cananian 1.1.2.2 import harpoon.IR.Quads.QuadKind; 18 cananian 1.1.2.2 import harpoon.IR.Quads.QuadFactory; 19 cananian 1.1.2.2 import harpoon.IR.Quads.CALL; 20 cananian 1.1.2.2 import harpoon.IR.Quads.CONST; 21 cananian 1.1.2.2 import harpoon.IR.Quads.NEW; 22 cananian 1.1.2.2 import harpoon.IR.Quads.ANEW; 23 cananian 1.1.2.2 import harpoon.IR.Quads.MONITORENTER; 24 cananian 1.1.2.2 import harpoon.IR.Quads.MONITOREXIT; 25 cananian 1.1.2.2 import harpoon.IR.Quads.Edge; 26 cananian 1.1.2.2 import harpoon.IR.LowQuad.LowQuadVisitor; 27 cananian 1.1.2.2 import harpoon.Temp.Temp; 28 cananian 1.1.2.2 import harpoon.Util.ArrayFactory; 29 cananian 1.1.2.2 import harpoon.Util.Util; 30 cananian 1.1.2.2 31 cananian 1.1.2.2 import java.util.ArrayList; 32 cananian 1.1.2.2 import java.util.List; 33 cananian 1.1.2.2 import java.util.Iterator; 34 cananian 1.1.2.2 import java.util.HashMap; 35 cananian 1.1.2.2 import java.util.HashSet; 36 cananian 1.1.2.2 import java.util.Map; 37 cananian 1.1.2.2 38 cananian 1.1.2.2 /** 39 cananian 1.1.2.2 * <code>InstrumentSyncOps</code> instruments synchronization operations for 40 cananian 1.1.2.2 * statistics-gathering purposes. 41 cananian 1.1.2.2 * 42 cananian 1.1.2.2 * @author John Whaley <jwhaley@alum.mit.edu> 43 salcianu 1.5 * @version $Id: InstrumentSyncOps.java,v 1.6 2003/02/03 16:24:23 salcianu Exp $ 44 cananian 1.1.2.2 */ 45 cananian 1.1.2.2 46 salcianu 1.1.2.5 public class InstrumentSyncOps implements java.io.Serializable { 47 cananian 1.1.2.2 48 cananian 1.3.2.2 static final HMethod new_method; 49 cananian 1.3.2.2 static final HMethod monitorenter_method; 50 cananian 1.3.2.2 static final HMethod monitorexit_method; 51 cananian 1.1.2.2 52 cananian 1.1.2.2 static { 53 cananian 1.1.2.2 Linker linker = Loader.systemLinker; 54 cananian 1.1.2.2 HClass instr_class = linker.forName("harpoon.Analysis.Quads.CollectSyncStats"); 55 cananian 1.1.2.2 new_method = instr_class.getDeclaredMethod("onNew", "(ILjava/lang/Object;I)V"); 56 cananian 1.1.2.2 monitorenter_method = instr_class.getDeclaredMethod("onMonitorEnter", "(ILjava/lang/Object;I)V"); 57 cananian 1.1.2.2 monitorexit_method = instr_class.getDeclaredMethod("onMonitorExit", "(ILjava/lang/Object;I)V"); 58 cananian 1.1.2.2 } 59 cananian 1.1.2.2 60 cananian 1.1.2.2 private PointerAnalysis pa; 61 cananian 1.1.2.2 private QuadMap newmap; // Map from new quads to id numbers. 62 cananian 1.1.2.2 private QuadMap monitorentermap; // Map from monitorenter quads to id numbers. 63 cananian 1.1.2.2 private QuadMap monitorexitmap; // Map from monitorexit quads to id numbers. 64 cananian 1.1.2.2 private HashMap locks[]; 65 cananian 1.1.2.2 private HashMap ocs[]; 66 cananian 1.1.2.2 67 cananian 1.1.2.2 public InstrumentSyncOps(PointerAnalysis pa) { 68 cananian 1.1.2.2 this.pa = pa; 69 cananian 1.1.2.2 this.newmap = new QuadMap(); 70 cananian 1.1.2.2 this.monitorentermap = new QuadMap(); 71 cananian 1.1.2.2 this.monitorexitmap = new QuadMap(); 72 jwhaley 1.1.2.4 this.ocs = new HashMap[2]; 73 cananian 1.1.2.2 this.ocs[0] = new HashMap(); 74 jwhaley 1.1.2.4 this.ocs[1] = new HashMap(); 75 jwhaley 1.1.2.4 this.locks = new HashMap[2]; 76 cananian 1.1.2.2 this.locks[0] = new HashMap(); 77 jwhaley 1.1.2.4 this.locks[1] = new HashMap(); 78 cananian 1.1.2.2 } 79 cananian 1.1.2.2 80 cananian 1.1.2.2 public void addRoot(MetaMethod mm) { 81 cananian 1.1.2.2 82 jwhaley 1.1.2.4 System.out.println("Adding analysis info from root method "+mm); 83 cananian 1.1.2.2 84 cananian 1.1.2.2 final ParIntGraph pig = pa.threadInteraction(mm); 85 cananian 1.1.2.2 final NodeRepository nr = pa.getNodeRepository(); 86 cananian 1.1.2.2 final ActionRepository ar = pig.ar; 87 cananian 1.1.2.2 88 cananian 1.1.2.2 // add to the set of inside ocs nodes. 89 cananian 1.1.2.2 PANodeVisitor node_visitor = new PANodeVisitor() { 90 cananian 1.1.2.2 public void visit(PANode n) { 91 cananian 1.1.2.2 if (!n.inside()) return; 92 cananian 1.1.2.2 HCodeElement hce = nr.node2Code(n); 93 cananian 1.1.2.2 if (hce == null) return; 94 cananian 1.1.2.2 //ProgramLocation l = new ProgramLocation(hce); 95 cananian 1.1.2.2 //ocs.put(l, n); 96 cananian 1.1.2.2 ocs[0].put(hce, n); // don't use ProgramLocation for now. 97 cananian 1.1.2.2 } 98 cananian 1.1.2.2 }; 99 cananian 1.1.2.2 pig.G.I.forAllNodes(node_visitor); 100 cananian 1.1.2.2 Iterator it; 101 cananian 1.1.2.2 it = pig.G.r.iterator(); 102 cananian 1.1.2.2 while (it.hasNext()) { 103 cananian 1.1.2.2 PANode n = (PANode)it.next(); 104 cananian 1.1.2.2 node_visitor.visit(n); 105 cananian 1.1.2.2 } 106 cananian 1.1.2.2 it = pig.G.excp.iterator(); 107 cananian 1.1.2.2 while (it.hasNext()) { 108 cananian 1.1.2.2 PANode n = (PANode)it.next(); 109 cananian 1.1.2.2 node_visitor.visit(n); 110 cananian 1.1.2.2 } 111 cananian 1.1.2.2 112 jwhaley 1.1.2.4 ActionVisitor act_visitor = new ActionVisitor() { 113 jwhaley 1.1.2.4 public void visit_ld(PALoad load){ 114 jwhaley 1.1.2.4 } 115 jwhaley 1.1.2.4 public void visit_sync(PASync sync){ 116 jwhaley 1.1.2.4 // this sync exists in the action repository, so it operates 117 jwhaley 1.1.2.4 // on an escaped node, therefore it is necessary. 118 jwhaley 1.1.2.4 HCodeElement hce = sync.hce; 119 jwhaley 1.1.2.4 if (hce != null) 120 jwhaley 1.1.2.4 locks[1].put(hce, sync); 121 jwhaley 1.1.2.4 } 122 jwhaley 1.1.2.4 }; 123 jwhaley 1.1.2.4 ar.forAllActions(act_visitor); 124 jwhaley 1.1.2.4 125 cananian 1.1.2.2 // add to the set of necessary sync ops. 126 cananian 1.1.2.2 // a sync op is necessary if it is executed in parallel with another 127 cananian 1.1.2.2 // thread that has a sync op on the same node. 128 cananian 1.1.2.2 ParActionVisitor par_act_visitor = new ParActionVisitor(){ 129 cananian 1.1.2.2 public void visit_par_ld(PALoad load, PANode nt2){ 130 cananian 1.1.2.2 } 131 cananian 1.1.2.2 public void visit_par_sync(PASync sync, PANode nt2){ 132 cananian 1.1.2.2 PANode n = sync.n; 133 cananian 1.1.2.2 PANode nt = sync.nt; 134 cananian 1.1.2.2 // Sync on node n is performed by nt in || with nt2. 135 cananian 1.1.2.2 // If nt2 has syncs on node n, this sync is necessary. 136 cananian 1.1.2.2 Iterator i = ar.syncsOn(n, nt2); 137 cananian 1.1.2.2 if (!i.hasNext()) return; 138 cananian 1.1.2.2 HCodeElement hce = sync.hce; 139 jwhaley 1.1.2.4 if (hce != null) 140 jwhaley 1.1.2.4 locks[0].put(hce, sync); 141 cananian 1.1.2.2 // Also add all syncs by nt2 on node n as necessary. 142 cananian 1.1.2.2 do { 143 cananian 1.1.2.2 PASync sync2 = (PASync)i.next(); 144 cananian 1.1.2.2 HCodeElement hce2 = sync.hce; 145 jwhaley 1.1.2.4 if (hce2 != null) 146 jwhaley 1.1.2.4 locks[0].put(hce2, sync2); 147 cananian 1.1.2.2 } while (i.hasNext()); 148 cananian 1.1.2.2 } 149 cananian 1.1.2.2 }; 150 cananian 1.1.2.2 ar.forAllParActions(par_act_visitor); 151 cananian 1.1.2.2 152 cananian 1.1.2.2 } 153 cananian 1.1.2.2 154 cananian 1.1.2.2 public void calculate() { 155 cananian 1.1.2.2 } 156 cananian 1.1.2.2 157 cananian 1.1.2.2 public void dumpMaps() { 158 cananian 1.1.2.2 System.out.println("OBJECT CREATION SITES:"); 159 cananian 1.1.2.2 newmap.dump(ocs[0]); 160 cananian 1.1.2.2 System.out.println("MONITORENTER:"); 161 jwhaley 1.1.2.4 monitorentermap.dump(locks[1]); 162 cananian 1.1.2.2 System.out.println("MONITOREXIT:"); 163 jwhaley 1.1.2.4 monitorexitmap.dump(locks[1]); 164 cananian 1.1.2.2 } 165 cananian 1.1.2.2 166 cananian 1.1.2.2 public HCode instrument(HCode hc) { 167 cananian 1.1.2.2 // Visit all quads. 168 cananian 1.1.2.2 List ql = hc.getElementsL(); 169 cananian 1.1.2.2 for (int i=0; i<ql.size(); ++i) { 170 cananian 1.1.2.2 Quad q = (Quad)ql.get(i); 171 cananian 1.1.2.2 int kind = q.kind(); 172 cananian 1.1.2.2 Temp dest; Integer id; 173 cananian 1.1.2.2 if ((kind == QuadKind.NEW) || (kind == QuadKind.ANEW)) { 174 cananian 1.1.2.2 if (kind == QuadKind.NEW) 175 cananian 1.1.2.2 dest = ((NEW)q).dst(); 176 cananian 1.1.2.2 else 177 cananian 1.1.2.2 dest = ((ANEW)q).dst(); 178 cananian 1.1.2.2 // get new id number 179 cananian 1.1.2.2 id = newmap.getNewID(q); 180 cananian 1.1.2.2 // add instrumentation after instruction 181 cananian 1.1.2.2 int val = 0; 182 cananian 1.1.2.2 if (ocs[0].get(q) != null) val += 1; 183 cananian 1.1.2.2 addInstrumentation(q, dest, new_method, id, new Integer(val)); 184 cananian 1.1.2.2 // update list position 185 cananian 1.1.2.2 ql = hc.getElementsL(); 186 cananian 1.1.2.2 i += 3; 187 cananian 1.1.2.2 } else if (kind == QuadKind.MONITORENTER) { 188 cananian 1.1.2.2 dest = ((MONITORENTER)q).lock(); 189 cananian 1.1.2.2 // get new id number 190 cananian 1.1.2.2 id = monitorentermap.getNewID(q); 191 cananian 1.1.2.2 // add instrumentation after instruction 192 cananian 1.1.2.2 int val = 0; 193 cananian 1.1.2.2 if (locks[0].get(q) != null) val += 1; 194 jwhaley 1.1.2.4 if (locks[1].get(q) != null) val += 2; 195 cananian 1.1.2.2 addInstrumentation(q, dest, monitorenter_method, id, 196 cananian 1.1.2.2 new Integer(val)); 197 cananian 1.1.2.2 // update list position 198 cananian 1.1.2.2 ql = hc.getElementsL(); 199 cananian 1.1.2.2 i += 3; 200 cananian 1.1.2.2 } else if (kind == QuadKind.MONITOREXIT) { 201 cananian 1.1.2.2 dest = ((MONITOREXIT)q).lock(); 202 cananian 1.1.2.2 // get new id number 203 cananian 1.1.2.2 id = monitorexitmap.getNewID(q); 204 cananian 1.1.2.2 // add instrumentation before instruction 205 cananian 1.1.2.2 int val = 0; 206 cananian 1.1.2.2 if (locks[0].get(q) != null) val += 1; 207 jwhaley 1.1.2.4 if (locks[1].get(q) != null) val += 2; 208 cananian 1.1.2.2 addInstrumentation(q, dest, monitorexit_method, id, 209 cananian 1.1.2.2 new Integer(val)); 210 cananian 1.1.2.2 // update list position 211 cananian 1.1.2.2 ql = hc.getElementsL(); 212 cananian 1.1.2.2 i += 3; 213 cananian 1.1.2.2 } 214 cananian 1.1.2.2 } 215 cananian 1.1.2.2 return hc; 216 cananian 1.1.2.2 } 217 cananian 1.1.2.2 218 cananian 1.1.2.2 private static void addInstrumentation(Quad q, Temp dest, HMethod method, Integer id, Integer id2) { 219 cananian 1.1.2.2 // use same quad factory as existing quad. 220 cananian 1.1.2.2 QuadFactory qf = q.getFactory(); 221 cananian 1.1.2.2 // generate a new temp to hold the id number. 222 cananian 1.1.2.2 Temp idTemp = new Temp(dest); 223 cananian 1.1.2.2 Temp idTemp2 = new Temp(idTemp); 224 cananian 1.1.2.2 // generate const quad. 225 cananian 1.1.2.2 CONST co = new CONST(qf, null, idTemp2, id2, HClass.Int); 226 cananian 1.1.2.2 // generate const quad. 227 cananian 1.1.2.2 CONST co2 = new CONST(qf, null, idTemp, id, HClass.Int); 228 cananian 1.1.2.2 // create param array for call. 229 cananian 1.1.2.2 Temp[] params = new Temp[3]; 230 cananian 1.1.2.2 params[0] = idTemp; 231 cananian 1.1.2.2 params[1] = dest; 232 cananian 1.1.2.2 params[2] = idTemp2; 233 cananian 1.1.2.2 // create a new call quad. 234 cananian 1.1.2.2 CALL ca = new CALL(qf, null, method, params, null, null, false, false, new Temp[0]); 235 cananian 1.1.2.2 // add the quads AFTER the NEW quad. 236 cananian 1.3.2.1 assert q.nextLength() == 1; 237 cananian 1.1.2.3 Edge ne = q.nextEdge(0); 238 cananian 1.1.2.2 Quad.addEdge(q, 0, co, 0); 239 cananian 1.1.2.2 Quad.addEdge(co, 0, co2, 0); 240 cananian 1.1.2.2 Quad.addEdge(co2, 0, ca, 0); 241 cananian 1.1.2.3 Quad.addEdge(ca, 0, (Quad)ne.to(), ne.which_pred()); 242 cananian 1.1.2.2 } 243 cananian 1.1.2.2 244 cananian 1.1.2.2 static class QuadMap { 245 cananian 1.1.2.2 246 cananian 1.1.2.2 ArrayList quads; 247 cananian 1.1.2.2 248 cananian 1.1.2.2 QuadMap() { quads = new ArrayList(); } 249 cananian 1.1.2.2 250 cananian 1.1.2.2 Integer getNewID(Quad q) { 251 cananian 1.1.2.2 quads.add(q); 252 cananian 1.1.2.2 return new Integer(quads.size()); 253 cananian 1.1.2.2 } 254 cananian 1.1.2.2 255 cananian 1.1.2.2 Quad getQuad(Integer i) { 256 cananian 1.1.2.2 return (Quad)quads.get(i.intValue()); 257 cananian 1.1.2.2 } 258 cananian 1.1.2.2 259 cananian 1.1.2.2 void dump(Map m) { 260 cananian 1.1.2.2 int num1 = 0; 261 cananian 1.1.2.2 for (int i=0; i<quads.size(); ++i) { 262 cananian 1.1.2.2 Quad q = (Quad)quads.get(i); 263 cananian 1.1.2.2 //ProgramLocation l = new ProgramLocation(q); 264 cananian 1.1.2.2 if (m != null) { 265 cananian 1.1.2.2 Object o = m.get(q); 266 cananian 1.1.2.2 if (o != null) { 267 cananian 1.1.2.2 System.out.print("necessary for: "+o); 268 cananian 1.1.2.2 ++num1; 269 cananian 1.1.2.2 } 270 cananian 1.1.2.2 } 271 cananian 1.1.2.2 System.out.println(" id "+(i+1)+": "+new ProgramLocation(q)); 272 cananian 1.1.2.2 } 273 cananian 1.1.2.2 System.out.println("Total number necessary: "+num1); 274 cananian 1.1.2.2 } 275 cananian 1.1.2.2 } 276 cananian 1.1.2.2 277 cananian 1.1.2.2 static class ProgramLocation { 278 cananian 1.1.2.2 String sourcefile; 279 cananian 1.1.2.2 int linenum; 280 cananian 1.1.2.2 281 cananian 1.1.2.2 ProgramLocation(HCodeElement hce) { 282 cananian 1.1.2.2 sourcefile = hce.getSourceFile(); 283 cananian 1.1.2.2 linenum = hce.getLineNumber(); 284 cananian 1.1.2.2 } 285 cananian 1.1.2.2 286 cananian 1.1.2.2 public boolean equals(ProgramLocation that) { 287 cananian 1.1.2.2 if (!this.sourcefile.equals(that.sourcefile)) return false; 288 cananian 1.1.2.2 if (this.linenum != that.linenum) return false; 289 cananian 1.1.2.2 return true; 290 cananian 1.1.2.2 } 291 cananian 1.1.2.2 292 cananian 1.1.2.2 public boolean equals(Object o) { 293 cananian 1.1.2.2 if (o instanceof ProgramLocation) return equals((ProgramLocation)o); 294 cananian 1.1.2.2 return false; 295 cananian 1.1.2.2 } 296 cananian 1.1.2.2 297 cananian 1.1.2.2 public int hashCode() { 298 cananian 1.1.2.2 return sourcefile.hashCode() ^ linenum; 299 cananian 1.1.2.2 } 300 cananian 1.1.2.2 301 cananian 1.1.2.2 public String toString() { 302 cananian 1.1.2.2 return sourcefile+":"+linenum; 303 cananian 1.1.2.2 } 304 cananian 1.1.2.2 } 305 cananian 1.1.2.2 306 cananian 1.1.2.2 307 cananian 1.1.2.2 /** Returns a <code>HCodeFactory</code> that uses <code>InstrumentSyncOps</code>. */ 308 cananian 1.1.2.2 public static HCodeFactory codeFactory(final HCodeFactory parent, final InstrumentSyncOps se) { 309 cananian 1.1.2.2 return new HCodeFactory() { 310 cananian 1.1.2.2 public HCode convert(HMethod m) { 311 cananian 1.1.2.2 HCode hc = parent.convert(m); 312 cananian 1.1.2.2 if (hc!=null) { 313 cananian 1.1.2.2 System.out.println("Instrumenting method "+m); 314 cananian 1.1.2.2 return se.instrument(hc); 315 cananian 1.1.2.2 } else 316 cananian 1.1.2.2 return hc; 317 cananian 1.1.2.2 } 318 cananian 1.1.2.2 public String getCodeName() { return parent.getCodeName(); } 319 cananian 1.1.2.2 public void clear(HMethod m) { parent.clear(m); } 320 cananian 1.1.2.2 }; 321 cananian 1.1.2.2 } 322 cananian 1.1.2.2 323 cananian 1.2 }