1 kkz 1.1.2.1 // AllocationHoisting.java, created Fri Oct 19 11:32:41 2001 by kkz 2 kkz 1.1.2.1 // Copyright (C) 2000 Karen Zee <kkz@tmi.lcs.mit.edu> 3 kkz 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 kkz 1.1.2.1 package harpoon.Analysis.PreciseGC; 5 kkz 1.1.2.1 6 kkz 1.1.2.1 import harpoon.Analysis.ClassHierarchy; 7 kkz 1.1.2.1 import harpoon.Analysis.ReachingDefs; 8 kkz 1.1.2.1 import harpoon.Analysis.ReachingDefsImpl; 9 kkz 1.1.2.3 import harpoon.ClassFile.CachingCodeFactory; 10 kkz 1.1.2.3 import harpoon.ClassFile.HClass; 11 kkz 1.1.2.1 import harpoon.ClassFile.HCodeAndMaps; 12 kkz 1.1.2.1 import harpoon.ClassFile.HCode; 13 kkz 1.1.2.1 import harpoon.ClassFile.HCodeFactory; 14 kkz 1.1.2.3 import harpoon.ClassFile.HMethod; 15 kkz 1.1.2.1 import harpoon.ClassFile.Linker; 16 kkz 1.1.2.3 import harpoon.ClassFile.SerializableCodeFactory; 17 kkz 1.1.2.3 import harpoon.IR.Quads.ANEW; 18 kkz 1.1.2.1 import harpoon.IR.Quads.ASET; 19 kkz 1.1.2.3 import harpoon.IR.Quads.CALL; 20 kkz 1.1.2.1 import harpoon.IR.Quads.Code; 21 kkz 1.1.2.3 import harpoon.IR.Quads.CONST; 22 kkz 1.1.2.3 import harpoon.IR.Quads.HEADER; 23 kkz 1.1.2.3 import harpoon.IR.Quads.METHOD; 24 kkz 1.1.2.3 import harpoon.IR.Quads.MOVE; 25 kkz 1.1.2.3 import harpoon.IR.Quads.NEW; 26 kkz 1.1.2.1 import harpoon.IR.Quads.Quad; 27 kkz 1.1.2.3 import harpoon.IR.Quads.QuadFactory; 28 kkz 1.1.2.1 import harpoon.IR.Quads.QuadKind; 29 kkz 1.1.2.3 import harpoon.IR.Quads.QuadVisitor; 30 kkz 1.1.2.1 import harpoon.IR.Quads.SET; 31 kkz 1.1.2.1 import harpoon.Temp.Temp; 32 kkz 1.1.2.3 import harpoon.Temp.TempFactory; 33 kkz 1.1.2.3 import harpoon.Util.Tuple; 34 kkz 1.1.2.1 import harpoon.Util.Util; 35 kkz 1.1.2.1 36 kkz 1.1.2.3 import java.util.HashMap; 37 kkz 1.1.2.1 import java.util.Iterator; 38 kkz 1.1.2.1 import java.util.Map; 39 kkz 1.1.2.1 import java.util.Set; 40 kkz 1.1.2.1 41 kkz 1.1.2.1 /** 42 kkz 1.1.2.1 * <code>AllocationHoisting</code> 43 kkz 1.1.2.1 * 44 kkz 1.1.2.1 * @author Karen Zee <kkz@tmi.lcs.mit.edu> 45 cananian 1.6 * @version $Id: AllocationHoisting.java,v 1.6 2004/02/08 03:20:07 cananian Exp $ 46 kkz 1.1.2.1 */ 47 kkz 1.1.2.1 public class AllocationHoisting extends 48 kkz 1.1.2.1 harpoon.Analysis.Transformation.MethodSplitter { 49 kkz 1.1.2.3 50 kkz 1.1.2.3 private final HCodeFactory parent; 51 kkz 1.1.2.3 private final ClassHierarchy ch; 52 kkz 1.1.2.3 private final Linker linker; 53 kkz 1.1.2.3 private final Map iMap; 54 kkz 1.1.2.3 private final Map iMap2; 55 kkz 1.1.2.1 private final MRAFactory mraf; 56 kkz 1.1.2.1 57 kkz 1.1.2.1 /** Token for the hoisted version of an initializer. */ 58 kkz 1.1.2.1 public static final Token HOISTED = new Token("allochoist") { 59 kkz 1.1.2.1 public Object readResolve() { return HOISTED; } 60 kkz 1.1.2.1 }; 61 kkz 1.1.2.3 /** Creates an <code>AllocationHoisting</code>. For efficiency, 62 kkz 1.1.2.3 * <code>parent</code> should be a <code>CachingCodeFactory</code>. 63 kkz 1.1.2.1 * @param parent The input code factory. 64 kkz 1.1.2.1 * @param ch A class hierarchy for the application. 65 kkz 1.1.2.1 */ 66 kkz 1.1.2.1 public AllocationHoisting(HCodeFactory parent, ClassHierarchy ch, 67 kkz 1.1.2.4 Linker l, String rName, int optLevel) { 68 kkz 1.1.2.1 super(parent, ch, true/*doesn't matter*/); 69 kkz 1.1.2.3 this.parent = parent; 70 kkz 1.1.2.3 this.ch = ch; 71 kkz 1.1.2.3 this.linker = l; 72 kkz 1.1.2.4 this.mraf = new MRAFactory(ch, parent, linker, rName, optLevel); 73 kkz 1.1.2.3 this.iMap = new HashMap(); 74 kkz 1.1.2.3 this.iMap2 = new HashMap(); 75 kkz 1.1.2.3 System.out.print("Setting up iMap..."); 76 kkz 1.1.2.3 setupiMap(rName); 77 kkz 1.1.2.3 System.out.println(" done!"); 78 kkz 1.1.2.1 } 79 kkz 1.1.2.3 80 kkz 1.1.2.3 /** Adds parameter to descriptors of mutated methods. */ 81 kkz 1.1.2.3 protected String mutateDescriptor(HMethod hm, Token which) { 82 kkz 1.1.2.3 String desc = hm.getDescriptor(); 83 kkz 1.1.2.3 if (which == HOISTED) { 84 kkz 1.1.2.3 Tuple tup = (Tuple) iMap.get(hm); 85 kkz 1.1.2.3 Quad q = (Quad) tup.proj(0); 86 kkz 1.1.2.3 HClass hc = (q.kind() == QuadKind.NEW) ? 87 kkz 1.1.2.3 ((NEW)q).hclass() : ((ANEW)q).hclass(); 88 kkz 1.1.2.3 int mid = desc.lastIndexOf(')'); 89 kkz 1.1.2.3 String cls = hc.getDescriptor(); 90 kkz 1.1.2.3 String result = desc.substring(0, mid) + hc.getDescriptor() + 91 kkz 1.1.2.3 desc.substring(mid, desc.length()); 92 kkz 1.1.2.3 //System.out.println(desc+" -> "+result); 93 kkz 1.1.2.3 return result; 94 kkz 1.1.2.3 } 95 kkz 1.1.2.3 return desc; 96 kkz 1.1.2.3 } 97 kkz 1.1.2.3 98 kkz 1.1.2.1 /** Hoists allocation out of the split method. */ 99 kkz 1.1.2.1 protected HCode mutateHCode(HCodeAndMaps input, Token which) { 100 kkz 1.1.2.1 Code c = (Code) input.hcode(); 101 kkz 1.1.2.3 if (which == HOISTED) { 102 kkz 1.1.2.3 hoistAlloc(c); 103 kkz 1.1.2.3 } else { 104 cananian 1.3.2.1 assert which == ORIGINAL; 105 kkz 1.1.2.3 Tuple tup = (Tuple) iMap.get(c.getMethod()); 106 kkz 1.1.2.3 if (tup != null) { 107 kkz 1.1.2.3 // remap 108 kkz 1.1.2.3 iMap.put(c.getMethod(), remap(tup, input.elementMap())); 109 kkz 1.1.2.3 } 110 kkz 1.1.2.3 modifyCalls(c); 111 kkz 1.1.2.3 } 112 kkz 1.1.2.3 // System.out.println(c.getMethod()+" is optimizable.\n"); 113 kkz 1.1.2.3 // c.print(new java.io.PrintWriter(System.out), null); 114 kkz 1.1.2.1 return input.hcode(); 115 kkz 1.1.2.1 } 116 kkz 1.1.2.3 117 kkz 1.1.2.3 /** Remaps the <code>Quad</code>s contained in the <code>Tuple</code> 118 kkz 1.1.2.3 * using the iven <code>Map</code>. 119 kkz 1.1.2.3 */ 120 kkz 1.1.2.3 private Tuple remap(Tuple tup, Map m) { 121 kkz 1.1.2.3 Quad q0 = (Quad) m.get((Quad)tup.proj(0)); 122 cananian 1.3.2.1 assert q0 != null; 123 kkz 1.1.2.3 if (q0.kind() == QuadKind.NEW) { 124 kkz 1.1.2.3 return new Tuple(new Object[] { q0 }); 125 kkz 1.1.2.3 } else { 126 cananian 1.3.2.1 assert q0.kind() == QuadKind.ANEW; 127 kkz 1.1.2.3 CONST[] orig = (CONST[]) tup.proj(1); 128 kkz 1.1.2.3 CONST[] cloned = new CONST[orig.length]; 129 kkz 1.1.2.3 for(int i = 0; i < cloned.length; i++) { 130 kkz 1.1.2.3 cloned[i] = (CONST) m.get(orig[i]); 131 cananian 1.3.2.1 assert cloned[i] != null; 132 kkz 1.1.2.3 } 133 kkz 1.1.2.3 return new Tuple(new Object[] { q0, cloned }); 134 kkz 1.1.2.3 } 135 kkz 1.1.2.3 } 136 kkz 1.1.2.3 137 kkz 1.1.2.3 /** Clones <code>HCode</code> and creates an <code>iMap2</code> 138 kkz 1.1.2.3 * entry for the cloned code. 139 kkz 1.1.2.3 */ 140 kkz 1.1.2.3 protected HCodeAndMaps cloneHCode(HCode hc, HMethod newmethod) 141 kkz 1.1.2.3 throws CloneNotSupportedException { 142 kkz 1.1.2.3 HCodeAndMaps hcam = hc.clone(newmethod); 143 kkz 1.1.2.3 Tuple tup = (Tuple) iMap.get(hc.getMethod()); 144 kkz 1.1.2.3 if (tup != null) { 145 kkz 1.1.2.3 iMap2.put(newmethod, remap(tup, hcam.elementMap())); 146 kkz 1.1.2.3 } 147 kkz 1.1.2.3 return hcam; 148 kkz 1.1.2.3 } 149 kkz 1.1.2.3 150 kkz 1.1.2.3 /** Removes the hoisted allocation from the initializer. */ 151 kkz 1.1.2.3 private Code hoistAlloc(Code c) { 152 kkz 1.1.2.3 Tuple tup = (Tuple) iMap2.get(c.getMethod()); 153 cananian 1.3.2.1 assert tup != null; 154 kkz 1.1.2.3 Quad q0 = (Quad) tup.proj(0); 155 kkz 1.1.2.3 Temp dst; 156 kkz 1.1.2.3 if (q0.kind() == QuadKind.NEW) { 157 kkz 1.1.2.3 dst = ((NEW)q0).dst(); 158 kkz 1.1.2.3 } else { 159 kkz 1.1.2.3 dst = ((ANEW)q0).dst(); 160 kkz 1.1.2.3 } 161 kkz 1.1.2.3 // create a new Temp for the new parameter 162 kkz 1.1.2.3 Temp newT = new Temp(q0.getFactory().tempFactory()); 163 kkz 1.1.2.3 METHOD oldM = ((HEADER)c.getRootElement()).method(); 164 kkz 1.1.2.3 Temp[] newTs = new Temp[oldM.paramsLength()+1]; 165 kkz 1.1.2.3 System.arraycopy(oldM.params(), 0, newTs, 0, oldM.paramsLength()); 166 kkz 1.1.2.3 newTs[newTs.length-1] = newT; 167 kkz 1.1.2.3 // create new METHOD with an additional parameter 168 kkz 1.1.2.3 METHOD newM = new METHOD(oldM.getFactory(), oldM, newTs, oldM.arity()); 169 kkz 1.1.2.3 Quad.replace(oldM, newM); 170 kkz 1.1.2.3 // replace allocation with assignment 171 kkz 1.1.2.3 MOVE m = new MOVE(q0.getFactory(), q0, dst, newT); 172 kkz 1.1.2.3 Quad.replace(q0, m); 173 kkz 1.1.2.3 //c.print(new java.io.PrintWriter(System.out), null); 174 kkz 1.1.2.3 return c; 175 kkz 1.1.2.3 } 176 kkz 1.1.2.3 177 kkz 1.1.2.3 /** Add hoisted allocation to code that calls the transformed 178 kkz 1.1.2.3 * initializers, and fix up calls. 179 kkz 1.1.2.3 */ 180 kkz 1.1.2.3 private Code modifyCalls(Code c) { 181 kkz 1.1.2.3 // go through all the Quads 182 kkz 1.1.2.3 for(Iterator it = c.getElementsI(); it.hasNext(); ) { 183 kkz 1.1.2.3 Quad q = (Quad) it.next(); 184 kkz 1.1.2.3 if (q.kind() == QuadKind.CALL) { 185 kkz 1.1.2.3 CALL call = (CALL)q; 186 kkz 1.1.2.3 Tuple tup = (Tuple) iMap.get(call.method()); 187 kkz 1.1.2.3 // replace call and add alloc if needed 188 kkz 1.1.2.3 if (tup != null) { 189 kkz 1.1.2.3 ReachingDefs rd = new ReachingDefsImpl(c); 190 kkz 1.1.2.3 Object[] defs = rd.reachingDefs 191 kkz 1.1.2.3 (call, call.params(0)).toArray(); 192 kkz 1.1.2.3 if (defs.length == 1 && 193 kkz 1.1.2.3 ((Quad)defs[0]).kind() == QuadKind.NEW) { 194 kkz 1.1.2.3 //System.out.println("Transforming "+call); 195 kkz 1.1.2.3 // create destination Temp for hoisted allocation 196 kkz 1.1.2.3 Temp dst = new Temp(call.getFactory().tempFactory()); 197 kkz 1.1.2.3 Quad template = (Quad) tup.proj(0); 198 kkz 1.1.2.3 // hoist allocation 199 kkz 1.1.2.3 if (template.kind() == QuadKind.NEW) { 200 kkz 1.1.2.3 addNEW((Quad)defs[0], dst, 201 kkz 1.1.2.3 ((NEW)template).hclass()); 202 kkz 1.1.2.3 } else { 203 cananian 1.3.2.1 assert template.kind() == QuadKind.ANEW; 204 kkz 1.1.2.3 addANEW((Quad)defs[0], dst, 205 kkz 1.1.2.3 ((ANEW)template).hclass(), 206 kkz 1.1.2.3 (CONST[])tup.proj(1)); 207 kkz 1.1.2.3 } 208 kkz 1.1.2.3 replaceCall(call, select(call.method(), HOISTED), dst); 209 kkz 1.1.2.3 } 210 kkz 1.1.2.3 } 211 kkz 1.1.2.3 } 212 kkz 1.1.2.3 } 213 kkz 1.1.2.3 return c; 214 kkz 1.1.2.3 } 215 kkz 1.1.2.3 216 kkz 1.1.2.3 /** Add NEW before given <code>Quad</code>, assigning to <code>t</code>. */ 217 kkz 1.1.2.3 private static void addNEW(Quad q, Temp t, HClass hc) { 218 kkz 1.1.2.3 Quad q0 = new NEW(q.getFactory(), q, t, hc); 219 cananian 1.3.2.1 assert q.prevLength() == 1; 220 kkz 1.1.2.3 Quad.addEdge(q.prev(0), q.prevEdge(0).which_succ(), q0, 0); 221 kkz 1.1.2.3 Quad.addEdge(q0, 0, q, 0); 222 kkz 1.1.2.3 } 223 kkz 1.1.2.3 224 kkz 1.1.2.3 /** Add ANEW and associated CONSTs (for the array dimensions) 225 kkz 1.1.2.3 * before the given <code>Quad</code>, assigning to <code>t</code>. 226 kkz 1.1.2.3 */ 227 kkz 1.1.2.3 private static void addANEW(Quad q, Temp t, HClass hc, CONST[] dims ) { 228 kkz 1.1.2.3 QuadFactory qf = q.getFactory(); 229 kkz 1.1.2.3 TempFactory tf = qf.tempFactory(); 230 kkz 1.1.2.3 Temp[] dimTs = new Temp[dims.length]; 231 kkz 1.1.2.3 Quad[] dimQs = new Quad[dims.length]; 232 kkz 1.1.2.3 // fill arrays 233 kkz 1.1.2.3 for(int i = 0; i < dims.length; i++) { 234 kkz 1.1.2.3 CONST orig = dims[i]; 235 kkz 1.1.2.3 dimTs[i] = new Temp(tf); 236 kkz 1.1.2.3 dimQs[i] = new CONST(qf, q, dimTs[i], orig.value(), orig.type()); 237 kkz 1.1.2.3 } 238 kkz 1.1.2.3 Quad q0 = new ANEW(q.getFactory(), q, t, hc, dimTs); 239 cananian 1.3.2.1 assert q.prevLength() == 1; 240 kkz 1.1.2.3 Quad.addEdge(q.prev(0), q.prevEdge(0).which_succ(), dimQs[0], 0); 241 kkz 1.1.2.3 // connect up the CONSTs 242 kkz 1.1.2.3 for(int i = 0; i < dimQs.length-1; i++) 243 kkz 1.1.2.3 Quad.addEdge(dimQs[i], 0, dimQs[i+1], 0); 244 kkz 1.1.2.3 Quad.addEdge(dimQs[dimQs.length-1], 0, q0, 0); 245 kkz 1.1.2.3 Quad.addEdge(q0, 0, q, 0); 246 kkz 1.1.2.3 } 247 kkz 1.1.2.3 248 kkz 1.1.2.3 /** Replaces original call with call to transformed method. 249 kkz 1.1.2.3 * @param orig is the original <code>CALL</code>. 250 kkz 1.1.2.3 * @param nhm is the <code>HMethod</code> to call. 251 kkz 1.1.2.3 * @param t is the <code>Temp</code> containing the last parameter. 252 kkz 1.1.2.3 */ 253 kkz 1.1.2.3 private static void replaceCall(CALL orig, HMethod nhm, Temp t) { 254 kkz 1.1.2.3 QuadFactory qf = orig.getFactory(); 255 kkz 1.1.2.3 // make new parameter array and copy over 256 kkz 1.1.2.3 Temp[] nparams = new Temp[orig.paramsLength()+1]; 257 kkz 1.1.2.3 System.arraycopy(orig.params(), 0, nparams, 0, orig.paramsLength()); 258 kkz 1.1.2.3 // the last parameter is the Temp containing the hoisted allocation 259 kkz 1.1.2.3 nparams[nparams.length-1] = t; 260 kkz 1.1.2.3 Quad ncall = new CALL(qf, orig, nhm, nparams, orig.retval(), 261 kkz 1.1.2.3 orig.retex(), orig.isVirtual(), 262 kkz 1.1.2.3 orig.isTailCall(), orig.dst(), orig.src()); 263 kkz 1.1.2.3 Quad.replace(orig, ncall); 264 kkz 1.1.2.3 Quad.transferHandlers(orig, ncall); 265 kkz 1.1.2.3 } 266 kkz 1.1.2.3 267 kkz 1.1.2.3 /** Initializes the <code>iMap</code> to a <code>Map</code> 268 kkz 1.1.2.3 * of initializers (<code>HMethod</code>s) that can benefit 269 kkz 1.1.2.3 * from this transform, to a <code>Tuple</code> containing 270 kkz 1.1.2.3 * the <code>HClass</code> of the allocation to be hoisted, 271 kkz 1.1.2.3 * and, if the allocation is of an array, the constant array 272 kkz 1.1.2.3 * dimensions. 273 kkz 1.1.2.3 * 274 kkz 1.1.2.3 * @param rName is the name of the path to the properties 275 kkz 1.1.2.3 * file that lists the native methods that do 276 kkz 1.1.2.3 * not allocate Java-visible objects 277 kkz 1.1.2.3 */ 278 kkz 1.1.2.3 private void setupiMap(String rName) { 279 cananian 1.6 for(Object hmO : ch.callableMethods()) { 280 cananian 1.6 HMethod hm = (HMethod) hmO; 281 kkz 1.4 // only consider initializers whose receiver 282 kkz 1.4 // is always the most recently allocated object 283 kkz 1.4 // on entry to the initializer 284 kkz 1.4 if (!hm.getName().equals("<init>") || 285 kkz 1.4 hm.getDeclaringClass().getName().startsWith("java.") || 286 kkz 1.4 hm.getDeclaringClass().getName().startsWith("sun.") || 287 kkz 1.4 !mraf.isSafeMethod(hm)) 288 kkz 1.4 continue; 289 kkz 1.1.2.3 Code c = (Code) parent.convert(hm); 290 kkz 1.1.2.3 // start with the beginning of the executable code 291 kkz 1.1.2.3 Quad q = ((HEADER)c.getRootElement()).method().next(0); 292 kkz 1.1.2.3 // only continue as long as the Quads are hoistable 293 kkz 1.1.2.3 for( ; (q.nextLength() == 1 && q.prevLength() == 1) || 294 kkz 1.1.2.3 q.kind() == QuadKind.CALL; q = q.next(0)) { 295 kkz 1.1.2.3 Temp src, dst; 296 kkz 1.1.2.3 if (q.kind() == QuadKind.ASET && 297 kkz 1.1.2.3 !((ASET)q).type().isPrimitive()) { 298 kkz 1.1.2.3 dst = ((ASET)q).objectref(); 299 kkz 1.1.2.3 src = ((ASET)q).src(); 300 kkz 1.1.2.3 } else if (q.kind() == QuadKind.SET && 301 kkz 1.1.2.3 !((SET)q).isStatic() && 302 kkz 1.1.2.3 !((SET)q).field().getType().isPrimitive()) { 303 kkz 1.1.2.3 dst = ((SET)q).objectref(); 304 kkz 1.1.2.3 src = ((SET)q).src(); 305 kkz 1.1.2.3 } else { 306 kkz 1.1.2.3 // most Quads can be ignored 307 kkz 1.1.2.3 continue; 308 kkz 1.1.2.3 } 309 kkz 1.1.2.3 // determine whether the given ASET/SET can be optimized 310 kkz 1.1.2.3 Tuple t = mraf.mra(c).mra_before(q); 311 kkz 1.1.2.3 MRA.MRAToken tok = (MRA.MRAToken) ((Map)t.proj(0)).get(src); 312 kkz 1.1.2.3 if (tok == MRA.MRAToken.SUCC /*is successor*/ && 313 kkz 1.1.2.3 ((Set)t.proj(1)).isEmpty() /*no exceptions*/ && 314 kkz 1.1.2.3 ((Set)t.proj(3)).contains(dst) /*writes to receiver*/) { 315 kkz 1.1.2.3 // single allocation site 316 cananian 1.3.2.1 assert (Quad)t.proj(2) != null; 317 kkz 1.1.2.3 Quad alloc = (Quad) t.proj(2); 318 kkz 1.1.2.3 if (alloc.kind() == QuadKind.NEW) { 319 kkz 1.1.2.3 iMap.put(hm, new Tuple(new Object[] { alloc })); 320 kkz 1.4 System.out.println(c.getMethod()+" is optimizable.\n"); 321 kkz 1.1.2.3 // done with this initializer 322 kkz 1.1.2.3 break; 323 kkz 1.1.2.3 } else { 324 cananian 1.3.2.1 assert alloc.kind() == QuadKind.ANEW; 325 kkz 1.1.2.3 boolean valid = true; 326 kkz 1.1.2.3 Temp[] dims = ((ANEW)alloc).dims(); 327 kkz 1.1.2.3 CONST[] consts = new CONST[dims.length]; 328 kkz 1.1.2.3 ReachingDefs rd = new ReachingDefsImpl(c); 329 kkz 1.1.2.3 for(int i = 0; i < dims.length; i++) { 330 kkz 1.1.2.3 Object[] defs = (Object[]) rd.reachingDefs 331 kkz 1.1.2.3 (alloc, dims[i]).toArray(); 332 kkz 1.1.2.3 if (defs.length == 1 && 333 kkz 1.1.2.3 ((Quad)defs[0]).kind() == QuadKind.CONST) { 334 kkz 1.1.2.3 consts[i] = (CONST) defs[0]; 335 kkz 1.1.2.3 } else { 336 kkz 1.1.2.3 valid = false; 337 kkz 1.1.2.3 break; 338 kkz 1.1.2.3 } 339 kkz 1.1.2.3 } 340 kkz 1.1.2.3 if (valid) { 341 kkz 1.1.2.3 iMap.put(hm, new Tuple(new Object[] 342 kkz 1.1.2.3 { alloc, consts })); 343 kkz 1.4 System.out.println(c.getMethod()+" is optimizable.\n"); 344 kkz 1.1.2.4 // done w/ this method 345 kkz 1.1.2.3 break; 346 kkz 1.1.2.3 } 347 kkz 1.1.2.3 } 348 kkz 1.1.2.3 } 349 kkz 1.1.2.3 } 350 kkz 1.1.2.3 } 351 kkz 1.1.2.3 } 352 kkz 1.1.2.3 353 kkz 1.1.2.1 /** Checks whether the given <code>Code</code> can benefit 354 kkz 1.1.2.1 * from the transformation. 355 kkz 1.1.2.1 */ 356 kkz 1.4 /* 357 kkz 1.1.2.1 private boolean optimizable(Code c) { 358 kkz 1.1.2.1 // only worry about safe initializers 359 kkz 1.1.2.4 if (!mraf.isSafeMethod(c.getMethod())) return false; 360 kkz 1.1.2.3 // check for SETs/ASETs that will benefit 361 kkz 1.1.2.1 MRA mra = mraf.mra(c); 362 kkz 1.1.2.1 for (Iterator it = c.getElementsI(); it.hasNext(); ) { 363 kkz 1.1.2.1 Quad q = (Quad) it.next(); 364 kkz 1.1.2.3 int kind = q.kind(); 365 kkz 1.1.2.1 Temp src, dst; 366 kkz 1.1.2.3 // check for non-primitive ASETs and SETs 367 kkz 1.1.2.3 // of non-primitive, non-static fields 368 kkz 1.1.2.3 if (kind == QuadKind.ASET && !((ASET)q).type().isPrimitive()) { 369 kkz 1.1.2.1 dst = ((ASET)q).objectref(); 370 kkz 1.1.2.1 src = ((ASET)q).src(); 371 kkz 1.1.2.3 } else if (kind == QuadKind.SET && !((SET)q).isStatic() && 372 kkz 1.1.2.1 !((SET)q).field().getType().isPrimitive()) { 373 kkz 1.1.2.1 dst = ((SET)q).objectref(); 374 kkz 1.1.2.1 src = ((SET)q).src(); 375 kkz 1.1.2.1 } else { 376 kkz 1.1.2.1 continue; 377 kkz 1.1.2.1 } 378 kkz 1.1.2.3 Tuple t = mra.mra_before(q); 379 kkz 1.1.2.3 MRA.MRAToken token = (MRA.MRAToken) ((Map)t.proj(0)).get(src); 380 kkz 1.1.2.3 if (token == MRA.MRAToken.SUCC && 381 kkz 1.1.2.3 ((Set)t.proj(1)).isEmpty()) { 382 kkz 1.1.2.3 Quad alloc = (Quad) t.proj(2); 383 kkz 1.1.2.3 if (alloc == null) return false; 384 kkz 1.1.2.3 // otherwise, see what we have 385 kkz 1.1.2.3 if (alloc.kind() == QuadKind.NEW) { 386 kkz 1.1.2.3 //System.out.println(q); 387 kkz 1.1.2.3 return true; 388 kkz 1.1.2.3 } else if (alloc.kind() == QuadKind.ANEW) { 389 kkz 1.1.2.3 Temp[] dims = ((ANEW)alloc).dims(); 390 kkz 1.1.2.3 // only want to handle if all dimensions are constants 391 kkz 1.1.2.3 for (int i = 0; i < dims.length; i++) { 392 kkz 1.1.2.3 Iterator ddefs = (new ReachingDefsImpl(c)). 393 kkz 1.1.2.3 reachingDefs(alloc, dims[i]).iterator(); 394 cananian 1.3.2.1 assert ddefs.hasNext(); 395 kkz 1.1.2.3 Quad dd = (Quad) ddefs.next(); 396 kkz 1.1.2.3 if (ddefs.hasNext()) return false; 397 kkz 1.1.2.3 if (dd.kind() != QuadKind.CONST) 398 kkz 1.1.2.3 return false; 399 kkz 1.1.2.1 } 400 kkz 1.1.2.3 //System.out.println(q); 401 kkz 1.1.2.3 return true; 402 kkz 1.1.2.1 } 403 kkz 1.1.2.3 } 404 kkz 1.1.2.1 } 405 kkz 1.1.2.1 return false; 406 kkz 1.1.2.1 } 407 kkz 1.4 */ 408 kkz 1.4 409 kkz 1.1.2.1 /** Check the validity of a given <code>MethodSplitter.Token</code>. 410 kkz 1.1.2.1 */ 411 kkz 1.1.2.1 protected boolean isValidToken(Token which) { 412 kkz 1.1.2.1 return which==HOISTED || super.isValidToken(which); 413 kkz 1.1.2.1 } 414 cananian 1.2 }