1 salcianu 1.1 // AllocationNumberingStub.java, created Sat Feb  1 19:45:56 2003 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.Instrumentation.AllocationStatistics;
  5 salcianu 1.1 
  6 salcianu 1.1 import java.util.Collection;
  7 salcianu 1.1 import java.util.Map;
  8 salcianu 1.1 import java.util.HashMap;
  9 salcianu 1.1 import java.util.Iterator;
 10 salcianu 1.1 import java.util.Set;
 11 salcianu 1.1 import java.util.HashSet;
 12 salcianu 1.1 
 13 salcianu 1.1 import java.io.IOException;
 14 salcianu 1.1 import java.io.FileReader;
 15 salcianu 1.1 import java.io.BufferedReader;
 16 salcianu 1.1 import java.io.PrintWriter;
 17 salcianu 1.1 import java.io.FileWriter;
 18 salcianu 1.1 import java.io.BufferedWriter;
 19 salcianu 1.1 
 20 salcianu 1.1 import harpoon.Util.DataStructs.Relation;
 21 salcianu 1.1 import harpoon.Util.DataStructs.RelationImpl;
 22 salcianu 1.1 
 23 salcianu 1.1 import harpoon.IR.Quads.Quad;
 24 salcianu 1.1 import harpoon.ClassFile.HMethod;
 25 salcianu 1.1 import harpoon.ClassFile.HClass;
 26 salcianu 1.1 import harpoon.ClassFile.Linker;
 27 salcianu 1.1 import harpoon.IR.Quads.Code;
 28 salcianu 1.1 
 29 salcianu 1.1 
 30 salcianu 1.1 /**
 31 salcianu 1.1  * <code>AllocationNumberingStub</code> is a very simple
 32 salcianu 1.1  * implementation of <code>AllocationNumberingInterf</code> designed
 33 salcianu 1.1  * to avoid serialization (serialization is buggy in many, if not all,
 34 salcianu 1.1  * JVMs).  Instead, <code>AllocationNumberingStub</code>s can be
 35 salcianu 1.1  * <i>textualized</i> to/from an ASCII file.
 36 salcianu 1.1  * 
 37 salcianu 1.1  * @author  Alexandru SALCIANU <salcianu@MIT.EDU>
 38 cananian 1.4  * @version $Id: AllocationNumberingStub.java,v 1.4 2004/02/08 03:21:32 cananian Exp $
 39 salcianu 1.1  */
 40 salcianu 1.1 public class AllocationNumberingStub implements AllocationNumberingInterf {
 41 salcianu 1.1 
 42 salcianu 1.1     // nobody can directly create such an object!
 43 salcianu 1.1     private AllocationNumberingStub() {}
 44 salcianu 1.1     
 45 salcianu 1.1     /** Create an <code>AllocationNumberingStub</code> by parsing a
 46 salcianu 1.1      text file.  This is the only approved way of creating an
 47 salcianu 1.1      <code>AllocationNumberingStub</code> object.
 48 salcianu 1.1 
 49 salcianu 1.1      @param linker Linker; given a string, gives the
 50 salcianu 1.1      <code>HClass</code> objects that represents the class with that
 51 salcianu 1.1      name (this is used mostly for convenience: it's easier to work
 52 salcianu 1.1      with <code>HClass</code>es and <code>HMethod</code>s instead of
 53 salcianu 1.1      just strings).
 54 salcianu 1.1 
 55 salcianu 1.1      @param filename Name of the file that contains the
 56 salcianu 1.1      <i>textualized</i> version of the
 57 salcianu 1.1      <code>AllocationNumberingStub</code>
 58 salcianu 1.1     */
 59 salcianu 1.1     public AllocationNumberingStub(Linker linker, String filename)
 60 salcianu 1.1         throws IOException {
 61 salcianu 1.1         BufferedReader br = new BufferedReader(new FileReader(filename));
 62 salcianu 1.1         int nb_methods = readInt(br);
 63 salcianu 1.1         for(int i = 0; i < nb_methods; i++)
 64 salcianu 1.1                 readMethodData(linker, br);     
 65 salcianu 1.1     }
 66 salcianu 1.1     
 67 salcianu 1.1     private final Map method2quadID2counter = new HashMap();
 68 salcianu 1.1     
 69 salcianu 1.1     private Map getMap4Method(HMethod hm) {
 70 salcianu 1.1         Map map = (Map) method2quadID2counter.get(hm);
 71 salcianu 1.1         if(map == null) {
 72 salcianu 1.1             map = new HashMap();
 73 salcianu 1.1             method2quadID2counter.put(hm, map);
 74 salcianu 1.1         }
 75 salcianu 1.1         return map;
 76 salcianu 1.1     }
 77 salcianu 1.1     
 78 salcianu 1.1     public int allocID(Quad q) {
 79 salcianu 1.1         HMethod hm = q.getFactory().getMethod();
 80 salcianu 1.1         Integer allocID = 
 81 salcianu 1.1             (Integer) getMap4Method(hm).get(new Integer(q.getID()));
 82 salcianu 1.3         if(allocID == null)
 83 salcianu 1.3             throw new UnknownAllocationSiteError
 84 salcianu 1.3                 ("Quad unknown: " + q + " #" + q.getID());
 85 salcianu 1.1         return allocID.intValue();
 86 salcianu 1.1     }
 87 salcianu 1.1 
 88 salcianu 1.1         
 89 salcianu 1.1     /////////////// PARSING METHODS ///////////////////////////////
 90 salcianu 1.1     private void readMethodData(Linker linker, BufferedReader br) 
 91 salcianu 1.1         throws IOException {
 92 salcianu 1.1         HMethod hm = readMethod(linker, br);
 93 salcianu 1.1         int nb_allocs = readInt(br);
 94 salcianu 1.1         for(int i = 0; i < nb_allocs; i++) {
 95 salcianu 1.1             int quadID = readInt(br);
 96 salcianu 1.1             int counter = readInt(br);
 97 salcianu 1.1             getMap4Method(hm).put
 98 salcianu 1.1                 (new Integer(quadID), new Integer(counter));
 99 salcianu 1.1         }
100 salcianu 1.1     }
101 salcianu 1.1     
102 salcianu 1.1     private static HClass readClass(Linker linker, BufferedReader br)
103 salcianu 1.1         throws IOException {
104 salcianu 1.1         String class_name = readString(br);
105 salcianu 1.1         HClass hc = (HClass) primitives.get(class_name);
106 salcianu 1.1         return (hc != null) ? hc : linker.forName(class_name);
107 salcianu 1.1     }
108 salcianu 1.1     
109 salcianu 1.1     private static Map primitives;
110 salcianu 1.1     static {
111 salcianu 1.1         primitives = new HashMap();
112 salcianu 1.1         primitives.put("boolean", HClass.Boolean);
113 salcianu 1.1         primitives.put("byte",    HClass.Byte);
114 salcianu 1.1         primitives.put("char"   , HClass.Char);
115 salcianu 1.1         primitives.put("double",  HClass.Double);
116 salcianu 1.1         primitives.put("float",   HClass.Float);
117 salcianu 1.1         primitives.put("int",     HClass.Int);
118 salcianu 1.1         primitives.put("long",    HClass.Long);
119 salcianu 1.1         primitives.put("short",   HClass.Short);
120 salcianu 1.1         primitives.put("void",    HClass.Void);
121 salcianu 1.1     }
122 salcianu 1.1     
123 salcianu 1.1     private static HMethod  readMethod(Linker linker, BufferedReader br)
124 salcianu 1.1         throws IOException {
125 salcianu 1.1         HClass hc = readClass(linker, br);
126 salcianu 1.1         String method_name = readString(br);
127 salcianu 1.1         int nb_params = readInt(br);
128 salcianu 1.1         HClass[] ptypes = new HClass[nb_params];
129 salcianu 1.1         for(int i = 0; i < nb_params; i++)
130 salcianu 1.1             ptypes[i] = readClass(linker, br);
131 salcianu 1.1         return hc.getMethod(method_name, ptypes);
132 salcianu 1.1     }
133 salcianu 1.1 
134 salcianu 1.1     private static int readInt(BufferedReader br) throws IOException {
135 salcianu 1.1         return new Integer(br.readLine()).intValue();
136 salcianu 1.1     }
137 salcianu 1.1 
138 salcianu 1.1     private static String readString(BufferedReader br) throws IOException {
139 salcianu 1.1         br.readLine(); // eat the line added as comment
140 salcianu 1.1         int size = readInt(br);
141 salcianu 1.1         char[] chars = new char[size];
142 salcianu 1.1         for(int i = 0; i < size; i++)
143 salcianu 1.1             chars[i] = (char) readInt(br);
144 salcianu 1.1         String str = new String(chars);
145 salcianu 1.1         return str;
146 salcianu 1.1     }
147 salcianu 1.1 
148 salcianu 1.1 
149 salcianu 1.1     ////////////////// MINI SERIALIZATON //////////////////////////////////
150 salcianu 1.1     /** Write into a file a simplified version of an
151 salcianu 1.1         AllocationNumbering object.  This method does a very simple
152 salcianu 1.1         serialization, I would call it <i>textualization</i>.  It
153 salcianu 1.1         outputs just enough information to retrieve the ID of each
154 salcianu 1.1         quad; the output has only ASCII characters.
155 salcianu 1.1 
156 salcianu 1.1         One can construct an <code>AllocationNumberingStub</code> stub
157 salcianu 1.1         from the textualized file image, using the appropriate
158 salcianu 1.1         constructor.
159 salcianu 1.1 
160 salcianu 1.1         @param an <code>AllocationNumbering</code> to textualize
161 salcianu 1.2 
162 salcianu 1.1         @param filename Name of the file to write the textualization into.
163 salcianu 1.2 
164 salcianu 1.2         @param linker Linker used to load the classes of the compiled
165 salcianu 1.2         program.  If non-null, it will be used to parse the file back
166 salcianu 1.2         into an <code>AllocationNumberingStub</code> and verify that
167 salcianu 1.2         the unique IDs for the allocation sites did not change.  If
168 salcianu 1.2         null, no verification will be performed.  */
169 salcianu 1.2     public static void writeToFile(AllocationNumbering an, String filename,
170 salcianu 1.2                                    Linker linker) throws IOException {
171 salcianu 1.1         PrintWriter pw =
172 salcianu 1.1             new PrintWriter(new BufferedWriter(new FileWriter(filename)));
173 salcianu 1.1         Relation method2allocs = getMethod2Allocs(an);
174 salcianu 1.1         writeInt(pw, method2allocs.keys().size());
175 cananian 1.4         for(Object hmO : method2allocs.keys()) {
176 cananian 1.4             HMethod hm = (HMethod) hmO;
177 salcianu 1.1             writeMethodSignature(pw, hm);
178 salcianu 1.1             writeAllocs(an, pw, method2allocs.getValues(hm));
179 salcianu 1.1         }
180 salcianu 1.1         pw.close();
181 salcianu 1.2         
182 salcianu 1.2         if(linker != null) {
183 salcianu 1.2             AllocationNumberingStub ans = 
184 salcianu 1.2                 new AllocationNumberingStub(linker, filename);
185 cananian 1.4             for(Object quadO : an.getAllocs()) {
186 cananian 1.4                 Quad quad = (Quad) quadO;
187 salcianu 1.2                 assert 
188 salcianu 1.2                     an.allocID(quad) == ans.allocID(quad) :
189 salcianu 1.2                     "Textualization error";
190 salcianu 1.2             }
191 salcianu 1.2         }
192 salcianu 1.1     }
193 salcianu 1.1 
194 salcianu 1.1     // produce a relation method m -> allocations sites inside m
195 salcianu 1.1     private static Relation getMethod2Allocs(AllocationNumbering an) {
196 salcianu 1.1         Relation method2allocs = new RelationImpl();
197 cananian 1.4         for(Object quadO : an.getAllocs()) {
198 cananian 1.4             Quad quad = (Quad) quadO;
199 salcianu 1.1             HMethod hm = quad.getFactory().getMethod();
200 salcianu 1.1             method2allocs.add(hm, quad);
201 salcianu 1.1         }
202 salcianu 1.1         return method2allocs;
203 salcianu 1.1     }
204 salcianu 1.1 
205 salcianu 1.1     // write to pw a textual representation of hm's signature
206 salcianu 1.1     private static void writeMethodSignature(PrintWriter pw, HMethod hm) {
207 salcianu 1.1         writeClass(pw, hm.getDeclaringClass());
208 salcianu 1.1         writeString(pw, hm.getName());
209 salcianu 1.1         HClass[] ptypes = hm.getParameterTypes();
210 salcianu 1.1         writeInt(pw, ptypes.length);
211 salcianu 1.1         for(int i = 0; i < ptypes.length; i++)
212 salcianu 1.1             writeClass(pw, ptypes[i]);
213 salcianu 1.1     }
214 salcianu 1.1 
215 salcianu 1.1     // write the name of the class hc to pw.
216 salcianu 1.1     private static void writeClass(PrintWriter pw, HClass hc) {
217 salcianu 1.1         writeString(pw, hc.getName());
218 salcianu 1.1     }
219 salcianu 1.1 
220 salcianu 1.1     // write to pw the unique identifiers for all allocations from allocs
221 salcianu 1.1     private static void writeAllocs(AllocationNumbering an,
222 salcianu 1.1                                     PrintWriter pw, Collection allocs) {
223 salcianu 1.1         writeInt(pw, allocs.size());
224 cananian 1.4         for(Object quadO : allocs) {
225 cananian 1.4             Quad quad = (Quad) quadO;
226 salcianu 1.1             writeInt(pw, quad.getID());
227 salcianu 1.1             writeInt(pw, an.allocID(quad));
228 salcianu 1.1         }
229 salcianu 1.1     }
230 salcianu 1.1 
231 salcianu 1.1     // write a single string to pw: the string is interpreted as an
232 salcianu 1.1     // array of characters (small ints).  We output the length of the
233 salcianu 1.1     // string (an integer), followed by the integers corresponding to
234 salcianu 1.1     // the characters from the string.  writeInt is employed for
235 salcianu 1.1     // displaying each integer.
236 salcianu 1.1     private static void writeString(PrintWriter pw, String str) {
237 salcianu 1.1         pw.println("// " + str); // added as a comment for debugging
238 salcianu 1.1         int length = str.length();
239 salcianu 1.1         writeInt(pw, length);
240 salcianu 1.1         for(int i = 0; i < length; i++)
241 salcianu 1.1             writeInt(pw, (int) str.charAt(i));
242 salcianu 1.1     }
243 salcianu 1.1 
244 salcianu 1.1     // write one integer to pw; each integer is on a line on its own
245 salcianu 1.1     private static void writeInt(PrintWriter pw, int i) {
246 salcianu 1.1         pw.println(i);
247 salcianu 1.1     }
248 salcianu 1.1 }