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     }