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 }