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     }