1 cananian 1.1.2.1 // GlobalFieldOracle.java, created Sun Jan 14 00:56:29 2001 by cananian 2 cananian 1.1.2.4 // Copyright (C) 2000 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.2.1 package harpoon.Analysis.Transactions; 5 cananian 1.1.2.1 6 cananian 1.1.2.1 import harpoon.Analysis.ClassHierarchy; 7 cananian 1.1.2.1 import harpoon.Analysis.DomTree; 8 cananian 1.1.2.1 import harpoon.Analysis.ReachingDefs; 9 cananian 1.1.2.1 import harpoon.Analysis.SSxReachingDefsImpl; 10 cananian 1.1.2.1 import harpoon.Analysis.Maps.ExactTypeMap; 11 cananian 1.1.2.1 import harpoon.Analysis.Quads.CallGraphImpl2; 12 cananian 1.1.2.1 import harpoon.Analysis.Quads.TypeInfo; 13 cananian 1.1.2.1 import harpoon.ClassFile.HCode; 14 cananian 1.1.2.1 import harpoon.ClassFile.HCodeFactory; 15 cananian 1.1.2.1 import harpoon.ClassFile.HField; 16 cananian 1.1.2.2 import harpoon.ClassFile.HInitializer; 17 cananian 1.1.2.1 import harpoon.ClassFile.HMethod; 18 cananian 1.1.2.1 import harpoon.IR.Quads.CALL; 19 cananian 1.1.2.1 import harpoon.IR.Quads.GET; 20 cananian 1.1.2.1 import harpoon.IR.Quads.MONITORENTER; 21 cananian 1.1.2.1 import harpoon.IR.Quads.MONITOREXIT; 22 cananian 1.1.2.1 import harpoon.IR.Quads.Quad; 23 cananian 1.1.2.1 import harpoon.IR.Quads.SET; 24 cananian 1.1.2.1 import harpoon.Util.ArrayIterator; 25 cananian 1.3 import net.cscott.jutil.WorkSet; 26 cananian 1.3 import net.cscott.jutil.AggregateSetFactory; 27 cananian 1.3 import net.cscott.jutil.GenericMultiMap; 28 cananian 1.3 import net.cscott.jutil.MultiMap; 29 cananian 1.3 import net.cscott.jutil.SetFactory; 30 cananian 1.1.2.1 31 cananian 1.1.2.1 import java.util.Arrays; 32 cananian 1.1.2.1 import java.util.HashSet; 33 cananian 1.1.2.1 import java.util.Iterator; 34 cananian 1.1.2.1 import java.util.Set; 35 cananian 1.1.2.1 /** 36 cananian 1.1.2.1 * A <code>GlobalFieldOracle</code> does a global analysis to determine 37 cananian 1.1.2.1 * which fields can possibly be accessed in unsynchronized and 38 cananian 1.1.2.1 * synchronized contexts. 39 cananian 1.1.2.1 * 40 cananian 1.1.2.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 41 cananian 1.4 * @version $Id: GlobalFieldOracle.java,v 1.4 2004/02/08 03:20:25 cananian Exp $ 42 cananian 1.1.2.1 */ 43 cananian 1.1.2.1 class GlobalFieldOracle extends FieldOracle { 44 cananian 1.1.2.1 Set syncRead = new HashSet(); Set syncWrite = new HashSet(); 45 cananian 1.1.2.1 Set unsyncRead = new HashSet(); Set unsyncWrite = new HashSet(); 46 cananian 1.1.2.1 public boolean isSyncRead(HField hf) { return syncRead.contains(hf); } 47 cananian 1.1.2.1 public boolean isSyncWrite(HField hf) { return syncWrite.contains(hf); } 48 cananian 1.1.2.1 public boolean isUnsyncRead(HField hf) { return unsyncRead.contains(hf); } 49 cananian 1.1.2.1 public boolean isUnsyncWrite(HField hf) { return unsyncWrite.contains(hf);} 50 cananian 1.1.2.1 51 cananian 1.1.2.1 /** Creates a <code>GlobalFieldOracle</code>. */ 52 cananian 1.1.2.1 public GlobalFieldOracle(ClassHierarchy ch, HMethod mainM, Set roots, 53 cananian 1.1.2.1 HCodeFactory hcf) { 54 cananian 1.1.2.3 /* Add callable static initializers to the root set */ 55 cananian 1.1.2.3 Set myroots = new HashSet(roots); 56 cananian 1.4 for (Object hmO : ch.callableMethods()) { 57 cananian 1.4 HMethod hm = (HMethod) hmO; 58 cananian 1.1.2.3 if (hm instanceof HInitializer) 59 cananian 1.1.2.3 myroots.add(hm); 60 cananian 1.1.2.3 } 61 cananian 1.1.2.1 /* for every method, compile lists of methods and fields which 62 cananian 1.1.2.1 * are accessed in synchronized and unsynchronized contexts. */ 63 cananian 1.1.2.1 MethodInfo mi = analyzeMethods(ch, hcf); 64 cananian 1.1.2.1 /* now determine which methods can possibly ever be called in 65 cananian 1.1.2.1 * syncronized and unsynchronized contexts. */ 66 cananian 1.1.2.3 CallContextInfo cci = new CallContextInfo(mi, mainM, myroots); 67 cananian 1.1.2.1 /* and finally, determine "possibly ever accessed" info for 68 cananian 1.1.2.1 * fields from the above. */ 69 cananian 1.1.2.1 transCloseFields(mi, cci); 70 cananian 1.1.2.3 { 71 cananian 1.1.2.3 Set sync = new HashSet(syncRead); sync.addAll(syncWrite); 72 cananian 1.1.2.3 Set unsync = new HashSet(unsyncRead); unsync.addAll(unsyncWrite); 73 cananian 1.1.2.3 Set common = new HashSet(sync); common.retainAll(unsync); 74 cananian 1.1.2.3 sync.removeAll(common); unsync.removeAll(common); 75 cananian 1.1.2.3 System.out.println("GLOBAL FIELD ORACLE: "+ 76 cananian 1.1.2.3 sync.size()+" fields exclusively sync, "+ 77 cananian 1.1.2.3 unsync.size()+" fields exclusively unsync"); 78 cananian 1.1.2.3 } 79 cananian 1.1.2.1 } 80 cananian 1.1.2.1 81 cananian 1.1.2.1 //---------------------------------------------------------------- 82 cananian 1.1.2.1 // method analysis 83 cananian 1.1.2.1 MethodInfo analyzeMethods(ClassHierarchy ch, HCodeFactory hcf) { 84 cananian 1.1.2.1 MethodInfo result = new MethodInfo(); 85 cananian 1.1.2.1 CallGraphImpl2 cg = new CallGraphImpl2(ch, hcf); 86 cananian 1.4 for (Object hmO : ch.callableMethods()) { 87 cananian 1.4 HMethod hm = (HMethod) hmO; 88 cananian 1.1.2.1 HCode hc = hcf.convert(hm); 89 cananian 1.1.2.1 if (hc==null) continue; 90 cananian 1.1.2.1 analyzeOneMethod(result, hm, hc, cg); 91 cananian 1.1.2.1 } 92 cananian 1.1.2.1 return result; 93 cananian 1.1.2.1 } 94 cananian 1.1.2.1 private void analyzeOneMethod(MethodInfo mi, HMethod hm, HCode hc, 95 cananian 1.1.2.1 CallGraphImpl2 cg) { 96 cananian 1.1.2.1 /* MONITORENTER must dominate all associated MONITOREXITs and 97 cananian 1.1.2.1 * monitors must be properly nested. */ 98 cananian 1.1.2.1 DomTree dt = new DomTree(hc, false); 99 cananian 1.1.2.1 ExactTypeMap etm = new TypeInfo((harpoon.IR.Quads.QuadSSI)hc); 100 cananian 1.1.2.1 ReachingDefs rd = new SSxReachingDefsImpl(hc); 101 cananian 1.1.2.1 analyzeOneQuad(mi, hm, (Quad)hc.getRootElement(), dt, etm, rd, cg, 0); 102 cananian 1.1.2.1 } 103 cananian 1.1.2.1 private void analyzeOneQuad(MethodInfo mi, HMethod hm, Quad q, DomTree dt, 104 cananian 1.1.2.1 ExactTypeMap etm, ReachingDefs rd, 105 cananian 1.1.2.1 CallGraphImpl2 cg, int synccount) { 106 cananian 1.1.2.1 /* analyze q */ 107 cananian 1.1.2.1 if (q instanceof MONITORENTER) synccount++; 108 cananian 1.1.2.1 if (q instanceof MONITOREXIT) synccount--; 109 cananian 1.1.2.1 if (q instanceof GET) { 110 cananian 1.1.2.1 MultiMap mm = (synccount>0) ? mi.readSync : mi.readUnsync; 111 cananian 1.1.2.1 mm.add(hm, ((GET)q).field()); 112 cananian 1.1.2.1 } 113 cananian 1.1.2.1 if (q instanceof SET) { 114 cananian 1.1.2.1 MultiMap mm = (synccount>0) ? mi.writeSync : mi.writeUnsync; 115 cananian 1.1.2.1 mm.add(hm, ((SET)q).field()); 116 cananian 1.1.2.1 } 117 cananian 1.1.2.1 if (q instanceof CALL) { 118 cananian 1.1.2.1 MultiMap mm = (synccount>0) ? mi.calledSync : mi.calledUnsync; 119 cananian 1.1.2.1 mm.addAll(hm, Arrays.asList(cg.calls((CALL)q, rd, etm))); 120 cananian 1.1.2.1 } 121 cananian 1.1.2.1 122 cananian 1.1.2.1 /* recurse down the dominator tree */ 123 cananian 1.1.2.1 for (Iterator it=new ArrayIterator(dt.children(q)); it.hasNext(); ) 124 cananian 1.1.2.1 analyzeOneQuad(mi,hm, (Quad)it.next(), dt,etm,rd,cg, synccount); 125 cananian 1.1.2.1 } 126 cananian 1.1.2.1 private class MethodInfo { 127 cananian 1.1.2.1 /** fields read/written in synchronized/unsynchronized contexts. */ 128 cananian 1.1.2.1 final MultiMap readSync, readUnsync, writeSync, writeUnsync; 129 cananian 1.1.2.1 /** methods called in synchronized/unsynchronized contexts. */ 130 cananian 1.1.2.1 final MultiMap calledSync, calledUnsync; 131 cananian 1.1.2.1 MethodInfo() { 132 cananian 1.1.2.1 SetFactory sf = new AggregateSetFactory(); 133 cananian 1.1.2.1 readSync = new GenericMultiMap(sf); 134 cananian 1.1.2.1 readUnsync = new GenericMultiMap(sf); 135 cananian 1.1.2.1 writeSync = new GenericMultiMap(sf); 136 cananian 1.1.2.1 writeUnsync = new GenericMultiMap(sf); 137 cananian 1.1.2.1 calledSync = new GenericMultiMap(sf); 138 cananian 1.1.2.1 calledUnsync = new GenericMultiMap(sf); 139 cananian 1.1.2.1 } 140 cananian 1.1.2.1 } 141 cananian 1.1.2.1 //---------------------------------------------------------------- 142 cananian 1.1.2.1 // compute transitive closure on methods called. 143 cananian 1.1.2.1 private class CallContextInfo { 144 cananian 1.1.2.1 final Set calledSync = new HashSet(); 145 cananian 1.1.2.1 final Set calledUnsync = new HashSet(); 146 cananian 1.1.2.1 /* compute call context info */ 147 cananian 1.1.2.1 CallContextInfo(MethodInfo mi, HMethod mainM, Set roots) { 148 cananian 1.1.2.1 WorkSet W = new WorkSet(); 149 cananian 1.1.2.1 // ever called unsync? 150 cananian 1.1.2.1 // if in calledUnsync list of a method ever called unsync. 151 cananian 1.1.2.1 W.addAll(roots); // all roots called unsync. 152 cananian 1.1.2.1 while (!W.isEmpty()) { 153 cananian 1.1.2.1 HMethod hm = (HMethod) W.pop(); 154 cananian 1.1.2.1 if (calledUnsync.contains(hm)) continue; 155 cananian 1.1.2.1 calledUnsync.add(hm); 156 cananian 1.1.2.1 W.addAll(mi.calledUnsync.getValues(hm)); 157 cananian 1.1.2.1 } 158 cananian 1.1.2.1 // ever called sync? 159 cananian 1.1.2.1 // if in any calledSync list 160 cananian 1.1.2.1 // or in calledUnsync list of a method ever called sync. 161 cananian 1.1.2.1 W.addAll(roots); // all roots called sync 162 cananian 1.1.2.1 W.remove(mainM); // except main method. 163 cananian 1.1.2.2 for (Iterator it=W.iterator(); it.hasNext(); ) 164 cananian 1.1.2.2 if (((HMethod)it.next()) instanceof HInitializer) 165 cananian 1.1.2.2 it.remove(); // and except static initializers. 166 cananian 1.4 for (Object hmO : mi.calledSync.keySet()){ 167 cananian 1.4 HMethod hm = (HMethod) hmO; 168 cananian 1.1.2.1 W.addAll(mi.calledSync.getValues(hm)); 169 cananian 1.1.2.1 } // add all calledSync to worklist. 170 cananian 1.1.2.1 while (!W.isEmpty()) { 171 cananian 1.1.2.1 HMethod hm = (HMethod) W.pop(); // a method called sync. 172 cananian 1.1.2.1 if (calledSync.contains(hm)) continue;//done already. 173 cananian 1.1.2.1 calledSync.add(hm); 174 cananian 1.1.2.1 // all unsync calls of a method called sync are called sync. 175 cananian 1.1.2.1 W.addAll(mi.calledUnsync.getValues(hm)); 176 cananian 1.1.2.1 } 177 cananian 1.1.2.1 // done. 178 cananian 1.1.2.1 } 179 cananian 1.1.2.1 } 180 cananian 1.1.2.1 //---------------------------------------------------------------- 181 cananian 1.1.2.1 // compute transitive closure on fields accessed. 182 cananian 1.1.2.1 void transCloseFields(MethodInfo mi, CallContextInfo cci) { 183 cananian 1.1.2.1 // ever accessed unsync? 184 cananian 1.1.2.1 // in fields accessedUnsync list of method called unsync. 185 cananian 1.4 for (Object hmO : cci.calledUnsync) { 186 cananian 1.4 HMethod hm = (HMethod) hmO; 187 cananian 1.1.2.1 unsyncRead.addAll(mi.readUnsync.getValues(hm)); 188 cananian 1.1.2.1 unsyncWrite.addAll(mi.writeUnsync.getValues(hm)); 189 cananian 1.1.2.1 } 190 cananian 1.1.2.1 // ever accessed sync? 191 cananian 1.1.2.1 // in any accessedSync list 192 cananian 1.1.2.1 // or in accessedUnsync list of a method called sync. 193 cananian 1.4 for (Object hmO : cci.calledUnsync) { 194 cananian 1.4 HMethod hm = (HMethod) hmO; 195 cananian 1.1.2.1 syncRead.addAll(mi.readSync.getValues(hm)); 196 cananian 1.1.2.1 syncWrite.addAll(mi.writeSync.getValues(hm)); 197 cananian 1.1.2.1 } 198 cananian 1.4 for (Object hmO : cci.calledSync) { 199 cananian 1.4 HMethod hm = (HMethod) hmO; 200 cananian 1.1.2.1 syncRead.addAll(mi.readSync.getValues(hm)); 201 cananian 1.1.2.1 syncRead.addAll(mi.readUnsync.getValues(hm)); 202 cananian 1.1.2.1 syncWrite.addAll(mi.writeSync.getValues(hm)); 203 cananian 1.1.2.1 syncWrite.addAll(mi.writeUnsync.getValues(hm)); 204 cananian 1.1.2.1 } 205 cananian 1.1.2.1 // done! 206 cananian 1.1.2.1 } 207 cananian 1.1.2.1 //---------------------------------------------------------------- 208 cananian 1.2 }