1 kkz      1.1 // RCTransformer.java, created Fri Feb  8 20:02:15 2002 by kkz
   2 kkz      1.1 // Copyright (C) 2000 Karen Zee <kkz@tmi.lcs.mit.edu>
   3 kkz      1.1 // Licensed under the terms of the GNU GPL; see COPYING for details.
   4 kkz      1.1 package harpoon.Analysis.PreciseGC;
   5 kkz      1.1 
   6 kkz      1.1 import harpoon.Analysis.ClassHierarchy;
   7 kkz      1.3 import harpoon.ClassFile.HClass;
   8 kkz      1.1 import harpoon.ClassFile.HCodeFactory;
   9 kkz      1.1 import harpoon.ClassFile.HCode;
  10 kkz      1.1 import harpoon.ClassFile.HCodeAndMaps;
  11 kkz      1.1 import harpoon.ClassFile.HMethod;
  12 kkz      1.3 import harpoon.ClassFile.Linker;
  13 kkz      1.1 import harpoon.IR.LowQuad.PCALL;
  14 kkz      1.1 import harpoon.IR.Properties.CFGEdge;
  15 kkz      1.1 import harpoon.IR.Properties.UseDefer;
  16 kkz      1.1 import harpoon.IR.Quads.CALL;
  17 kkz      1.1 import harpoon.IR.Quads.CJMP;
  18 kkz      1.1 import harpoon.IR.Quads.Code;
  19 kkz      1.1 import harpoon.IR.Quads.FOOTER;
  20 kkz      1.1 import harpoon.IR.Quads.METHOD;
  21 kkz      1.1 import harpoon.IR.Quads.NEW;
  22 kkz      1.1 import harpoon.IR.Quads.OPER;
  23 kkz      1.1 import harpoon.IR.Quads.PHI;
  24 kkz      1.1 import harpoon.IR.Quads.Quad;
  25 kkz      1.1 import harpoon.IR.Quads.QuadFactory;
  26 kkz      1.1 import harpoon.IR.Quads.QuadKind;
  27 kkz      1.1 import harpoon.IR.Quads.QuadVisitor;
  28 kkz      1.1 import harpoon.IR.Quads.RETURN;
  29 kkz      1.1 import harpoon.IR.Quads.SET;
  30 kkz      1.1 import harpoon.IR.Quads.SIGMA;
  31 kkz      1.1 import harpoon.IR.Quads.SWITCH;
  32 kkz      1.1 import harpoon.IR.Quads.THROW;
  33 kkz      1.1 import harpoon.IR.Quads.TYPESWITCH;
  34 kkz      1.1 import harpoon.Temp.Temp;
  35 kkz      1.1 import harpoon.Temp.TempFactory;
  36 kkz      1.1 import harpoon.Util.Tuple;
  37 kkz      1.1 import harpoon.Util.Util;
  38 kkz      1.1 import harpoon.Util.Worklist;
  39 cananian 1.2 import harpoon.Util.Collections.WorkSet;
  40 kkz      1.1 
  41 kkz      1.1 import java.lang.reflect.Modifier;
  42 kkz      1.1 import java.util.ArrayList;
  43 kkz      1.1 import java.util.Collections;
  44 kkz      1.1 import java.util.HashMap;
  45 kkz      1.1 import java.util.HashSet;
  46 kkz      1.1 import java.util.Iterator;
  47 kkz      1.1 import java.util.List;
  48 kkz      1.1 import java.util.Map;
  49 kkz      1.1 import java.util.Set;
  50 kkz      1.1 
  51 kkz      1.1 /**
  52 kkz      1.1  * <code>RCTransformer</code> transforms recursive constructors
  53 kkz      1.1  * that build their data structures in a top-down fashion into 
  54 kkz      1.1  * methods that build their data structures in a bottom-up fashion.
  55 kkz      1.1  * Also transforms the callers of these methods.
  56 kkz      1.1  * 
  57 kkz      1.1  * @author  Karen Zee <kkz@tmi.lcs.mit.edu>
  58 cananian 1.5  * @version $Id: RCTransformer.java,v 1.5 2004/02/08 03:20:07 cananian Exp $
  59 kkz      1.1  */
  60 kkz      1.1 public class RCTransformer extends 
  61 kkz      1.1     harpoon.Analysis.Transformation.MethodSplitter {
  62 kkz      1.1 
  63 kkz      1.1     private final Set recursiveConstructors;
  64 kkz      1.1 
  65 kkz      1.1     /** Creates a <code>RCTransformer</code>. */
  66 kkz      1.3     public RCTransformer(HCodeFactory parent, ClassHierarchy ch, Linker lnkr) {
  67 kkz      1.1         super(parent, ch, true/* doesn't matter */);
  68 kkz      1.1         this.recursiveConstructors = new HashSet();
  69 kkz      1.3         scanConstructors(parent, ch, lnkr);
  70 kkz      1.1         System.out.println(recursiveConstructors.size() + " constructors");
  71 kkz      1.1     }
  72 kkz      1.1     
  73 kkz      1.1     /** The <code>CREATOR</code> token represents the transformed
  74 kkz      1.1      *  version of the method. */
  75 kkz      1.1     public static final Token CREATOR = new Token("creator") {
  76 kkz      1.1         public Object readResolve() { return CREATOR; }
  77 kkz      1.1         public String toString() { return "TOKEN<CREATOR>"; }
  78 kkz      1.1     };
  79 kkz      1.1 
  80 kkz      1.1     /** Mutated constructors have signatures differing from the
  81 kkz      1.1      *  original.
  82 kkz      1.1      */
  83 kkz      1.1     protected String mutateDescriptor(HMethod hm, Token which) {
  84 kkz      1.1         if (which != CREATOR) {
  85 kkz      1.1             return hm.getDescriptor();
  86 kkz      1.1         } else {
  87 kkz      1.1             String desc = hm.getDescriptor();
  88 kkz      1.1             return desc.substring(0,desc.length()-1) + 
  89 kkz      1.1                 hm.getDeclaringClass().getDescriptor();
  90 kkz      1.1         }
  91 kkz      1.1     }
  92 kkz      1.1 
  93 kkz      1.1     /** Modifies two classes of methods:
  94 kkz      1.1      *  - mutates recursive constructors into "creators", methods
  95 kkz      1.1      *    that build objects in a bottom-up fashion
  96 kkz      1.1      *  - modifies callers of these constructors to call the new
  97 kkz      1.1      *    creator methods
  98 kkz      1.1      */
  99 kkz      1.1     protected HCode mutateHCode(HCodeAndMaps input, Token which) {
 100 kkz      1.1         Code c = (Code) input.hcode();
 101 kkz      1.1         if (recursiveConstructors.size() == 0) {
 102 kkz      1.1             // no need to make changes if no
 103 kkz      1.1             // constructors are modifiable
 104 kkz      1.1             return c;
 105 kkz      1.1         } else if (which == CREATOR) {
 106 kkz      1.1             makeCreator(c);
 107 kkz      1.1         }
 108 kkz      1.1         // modify calls for all methods including
 109 kkz      1.1         // newly-minted creator methods
 110 kkz      1.1         return modifyCalls(c);
 111 kkz      1.1     }
 112 kkz      1.1 
 113 kkz      1.1     /** Convert recursive constructor to a recursive
 114 kkz      1.1      *  creator method.
 115 kkz      1.1      */
 116 kkz      1.1     private Code makeCreator(Code c) {
 117 kkz      1.1         // find call to superclass constructor
 118 kkz      1.3         //System.out.println("Making creator");
 119 kkz      1.3         //c.print(new java.io.PrintWriter(System.out), null);
 120 kkz      1.1         Quad q = (Quad) c.getRootElement();
 121 kkz      1.1         CFGEdge[] succs = q.succ();
 122 kkz      1.1         // first Quad should be the HEADER
 123 cananian 1.4         assert q.kind() == QuadKind.HEADER && succs.length == 2;
 124 kkz      1.1         q = (Quad) succs[1].to();
 125 kkz      1.1         succs = q.succ();
 126 kkz      1.1         // second Quad should be the METHOD
 127 cananian 1.4         assert q.kind() == QuadKind.METHOD && succs.length == 1;
 128 kkz      1.1         METHOD omethod = (METHOD)q;
 129 kkz      1.1         // get a handle on the METHOD parameters
 130 kkz      1.1         Temp[] oparams = omethod.params();
 131 kkz      1.1         Temp retval = oparams[0];
 132 kkz      1.1         // replace METHOD
 133 kkz      1.1         METHOD nmethod = replaceMETHOD(omethod, oparams);
 134 kkz      1.1         q = (Quad) succs[0].to();
 135 kkz      1.1         succs = q.succ();
 136 kkz      1.1         // third Quad should be the CALL to the superclass constructor
 137 cananian 1.4         assert q.kind() == QuadKind.CALL;
 138 kkz      1.1         CALL call = (CALL)q;
 139 cananian 1.4         assert call.retval() == null && call.params(0).equals(retval);
 140 kkz      1.1         // create a NEW
 141 kkz      1.1         NEW nnew = new NEW(call.getFactory(), call, retval, 
 142 kkz      1.1                            c.getMethod().getDeclaringClass());
 143 kkz      1.1         // put NEW before CALL (and after METHOD)
 144 cananian 1.4         assert call.prevLength() == 1;
 145 kkz      1.1         Quad.addEdge(call.prev(0), call.prevEdge(0).which_succ(), nnew, 0);
 146 kkz      1.1         Quad.addEdge(nnew, 0, call, 0);
 147 kkz      1.1         // fix-up RETURN(s)
 148 kkz      1.1         call.accept(new RETURNFixUp(retval));
 149 kkz      1.3         //c.print(new java.io.PrintWriter(System.out), null);
 150 kkz      1.1         // start with the Quad on the 0-edge (normal return)
 151 kkz      1.1         // of the call to the superclass constructor, and
 152 kkz      1.1         // find the straight-line code that we want to move
 153 kkz      1.1         findChain fc = new findChain(retval, nnew, call);
 154 kkz      1.1         Quad end = fc.end;
 155 kkz      1.1         fc = null;
 156 kkz      1.3         //System.out.println(end);
 157 kkz      1.1         findTemps ft = new findTemps(nmethod, nnew, call, end);
 158 kkz      1.1         checkDependencies cd = new checkDependencies(nmethod, nnew, call, end);
 159 kkz      1.1         // only perform transformation if possible
 160 kkz      1.1         if (ft.needs.size() == 0 && ft.safe && cd.safe) {
 161 kkz      1.3             //System.out.println("Safe...");
 162 kkz      1.1             updateDependencies ud = new updateDependencies(nmethod, nnew, call,
 163 kkz      1.1                                                            end, c.getMethod());
 164 kkz      1.3             //c.print(new java.io.PrintWriter(System.out), null);
 165 kkz      1.1             Map insertPts = ud.insertPts;
 166 kkz      1.1             // null out for GC
 167 kkz      1.1             ud = null;
 168 kkz      1.3             /*
 169 cananian 1.5             for(Object keyO : insertPts.keySet())
 170 kkz      1.1                 {
 171 cananian 1.5                     Quad key = (Quad) keyO;
 172 kkz      1.1                     Quad[] value = (Quad[]) insertPts.get(key);
 173 kkz      1.1                     System.out.println(key);
 174 kkz      1.1                     for(int i = 0; i < value.length; i++) {
 175 kkz      1.1                         System.out.println(":: "+value[i]);
 176 kkz      1.1                     }
 177 kkz      1.1                 }
 178 kkz      1.1             System.out.println("Done...");
 179 kkz      1.3             */
 180 kkz      1.1             makeRecurse mr = new makeRecurse(insertPts, nnew);
 181 kkz      1.3             //c.print(new java.io.PrintWriter(System.out), null);
 182 kkz      1.1             nmethod.next(0).accept(mr);
 183 kkz      1.3             //c.print(new java.io.PrintWriter(System.out), null);
 184 kkz      1.1         }
 185 kkz      1.1         return c;
 186 kkz      1.1     }
 187 kkz      1.1 
 188 kkz      1.1 
 189 kkz      1.1 
 190 kkz      1.1     /** Replaces the <code>METHOD</code> <code>Quad</code> of the
 191 kkz      1.1      *  creator method with a corrected one.
 192 kkz      1.1      */
 193 kkz      1.1     private METHOD replaceMETHOD(METHOD omethod, Temp[] oparams) {
 194 kkz      1.1         Temp[] nparams = new Temp[oparams.length-1];
 195 kkz      1.1         // create a new METHOD with the right parameters
 196 kkz      1.1         System.arraycopy(oparams, 1, nparams, 0, nparams.length);
 197 kkz      1.1         METHOD nmethod = new METHOD(omethod.getFactory(), omethod, 
 198 kkz      1.1                                     nparams, omethod.arity());
 199 kkz      1.1         Quad.replace(omethod, nmethod);
 200 kkz      1.1         return nmethod;
 201 kkz      1.1     }
 202 kkz      1.1 
 203 kkz      1.1 
 204 kkz      1.1     /** Replaces a call to a recursive constructor with a
 205 kkz      1.1      *  call to the new creator method.
 206 kkz      1.1      */
 207 kkz      1.1     private Code modifyCalls(Code c) {
 208 kkz      1.1         for(Iterator it = c.getElementsI(); it.hasNext(); ) {
 209 kkz      1.1             Quad q = (Quad) it.next();
 210 kkz      1.1             // modify callers of recursive constructors
 211 kkz      1.1             // so that they call "creators" instead
 212 kkz      1.1             if (q.kind() == QuadKind.CALL) {
 213 kkz      1.1                 CALL call = (CALL) q;
 214 kkz      1.1                 if (recursiveConstructors.contains(call.method())) {
 215 kkz      1.1                     // find allocation site of object being initialized
 216 kkz      1.1                     CFGEdge[] preds = q.pred();
 217 kkz      1.1                     if (preds.length == 1) {
 218 kkz      1.1                         Quad pred = (Quad) preds[0].from();
 219 kkz      1.1                         if (pred.kind() == QuadKind.NEW && 
 220 kkz      1.1                             ((NEW)pred).dst().equals(call.params(0))) {
 221 kkz      1.1                             HMethod nhm = select(call.method(), CREATOR);
 222 kkz      1.1                             replaceCall(call, (NEW)pred, nhm);
 223 kkz      1.1                             //select(call.method(), CREATOR));
 224 kkz      1.1                         }
 225 kkz      1.1                     }
 226 kkz      1.1                 }
 227 kkz      1.1             }
 228 kkz      1.1         }
 229 kkz      1.1         return c;
 230 kkz      1.1     }
 231 kkz      1.1     
 232 kkz      1.1     /** Helper method that actually updates the graph by 
 233 kkz      1.1      *  replacing a call to a recursive constructor with
 234 kkz      1.1      *  a call to the new creator method.
 235 kkz      1.1      */
 236 kkz      1.1     private static void replaceCall(CALL ocall, NEW alloc, HMethod nhm) {
 237 kkz      1.1         // hack to turn constructor into static method
 238 kkz      1.1         nhm.getMutator().addModifiers(Modifier.STATIC);
 239 kkz      1.1         Temp[] nparams = new Temp[ocall.paramsLength()-1];
 240 kkz      1.1         System.arraycopy(ocall.params(), 1, nparams, 0, nparams.length);
 241 cananian 1.4         assert ocall.retval() == null;
 242 kkz      1.1         CALL ncall = new CALL(ocall.getFactory(), ocall, nhm, nparams,
 243 kkz      1.1                               ocall.params(0), ocall.retex(), 
 244 kkz      1.1                               ocall.isVirtual(), ocall.isTailCall(),
 245 kkz      1.1                               ocall.dst(), ocall.src());
 246 kkz      1.3         /*
 247 kkz      1.3           System.out.println("Replacing:");
 248 kkz      1.1         System.out.println(alloc);
 249 kkz      1.1         System.out.println(ocall);
 250 kkz      1.1         System.out.println("with");
 251 kkz      1.1         System.out.println(ncall);
 252 kkz      1.3         */
 253 kkz      1.1         // update graph
 254 kkz      1.1         alloc.remove();
 255 kkz      1.1         Quad.replace(ocall,ncall);
 256 kkz      1.1         Quad.transferHandlers(ocall,ncall);
 257 kkz      1.1     }
 258 kkz      1.1 
 259 kkz      1.3     private void scanConstructors(HCodeFactory parent, ClassHierarchy ch,
 260 kkz      1.3                                   Linker lnkr) {
 261 kkz      1.1         // first, find constructors that call themselves
 262 cananian 1.5         for(Object hmO : ch.callableMethods()) {
 263 cananian 1.5             HMethod hm = (HMethod) hmO;
 264 kkz      1.1             // skip methods that are not constructors
 265 kkz      1.1             if (!hm.getName().equals("<init>")) continue;
 266 kkz      1.1             Code c = (Code) parent.convert(hm);
 267 kkz      1.3             boolean recursive = false;
 268 kkz      1.1             // look for constructors that call themselves
 269 kkz      1.1             for(Iterator quads = c.getElementsI(); quads.hasNext(); ) {
 270 kkz      1.1                 Quad q = (Quad) quads.next();
 271 kkz      1.1                 if (q.kind() == QuadKind.CALL &&
 272 kkz      1.1                     ((CALL)q).method().equals(hm)) {
 273 kkz      1.1                     recursiveConstructors.add(hm);
 274 kkz      1.3                     recursive = true;
 275 kkz      1.1                     break;
 276 kkz      1.1                 }
 277 kkz      1.1             }
 278 kkz      1.3             // make sure we can handle all the Quads in them
 279 kkz      1.3             if (recursive) {
 280 kkz      1.3                 HClass exc = lnkr.forName("java.lang.Throwable");
 281 kkz      1.3                 for(Iterator quads = c.getElementsI(); quads.hasNext(); ) {
 282 kkz      1.3                     Quad q = (Quad) quads.next();
 283 kkz      1.3                     // we currently only handle a subset of Quads
 284 kkz      1.3                     if (q.kind() == QuadKind.NEW) {
 285 kkz      1.3                         HClass hcls = ((NEW)q).hclass();
 286 kkz      1.3                         if (!hcls.equals(hm.getDeclaringClass()) &&
 287 kkz      1.3                             !hcls.isInstanceOf(exc)) {
 288 kkz      1.3                             recursiveConstructors.remove(hm);
 289 kkz      1.3                             break;
 290 kkz      1.3                         }
 291 kkz      1.3                     } else if (q.kind() != QuadKind.CALL &&
 292 kkz      1.3                                q.kind() != QuadKind.CJMP &&
 293 kkz      1.3                                q.kind() != QuadKind.CONST &&
 294 kkz      1.3                                q.kind() != QuadKind.FOOTER &&
 295 kkz      1.3                                q.kind() != QuadKind.HEADER &&
 296 kkz      1.3                                q.kind() != QuadKind.METHOD &&
 297 kkz      1.3                                q.kind() != QuadKind.OPER &&
 298 kkz      1.3                                q.kind() != QuadKind.PHI &&
 299 kkz      1.3                                q.kind() != QuadKind.RETURN &&
 300 kkz      1.3                                q.kind() != QuadKind.SET &&
 301 kkz      1.3                                q.kind() != QuadKind.THROW) {
 302 kkz      1.3                         recursiveConstructors.remove(hm);
 303 kkz      1.3                         break;
 304 kkz      1.3                     }
 305 kkz      1.3                 }
 306 kkz      1.3             }
 307 kkz      1.1         }
 308 kkz      1.1     }
 309 kkz      1.1 
 310 kkz      1.1     /** Check the validity of a given <code>MethodSplitter.Token</code>.
 311 kkz      1.1      */
 312 kkz      1.1     protected boolean isValidToken(Token which) {
 313 kkz      1.1         return which == CREATOR || super.isValidToken(which);
 314 kkz      1.1     }
 315 kkz      1.1 
 316 kkz      1.1     /** private class for traversing the graph to fix-up the
 317 kkz      1.1      *  RETURN nodes.
 318 kkz      1.1      */
 319 kkz      1.1     private static class RETURNFixUp extends QuadVisitor
 320 kkz      1.1     {
 321 kkz      1.1         Temp retval;
 322 kkz      1.1         int nParam;
 323 kkz      1.1         Map done;
 324 kkz      1.1 
 325 kkz      1.1         RETURNFixUp(Temp retval) {
 326 kkz      1.1             this.retval = retval;
 327 kkz      1.1             this.nParam = 0;
 328 kkz      1.1             this.done = new HashMap();
 329 kkz      1.1         }
 330 kkz      1.1 
 331 kkz      1.1         public void visit(CALL q) {
 332 kkz      1.1             for(int i = 0; i < q.numSigmas(); i++) {
 333 kkz      1.1                 if (q.src(i).equals(retval)) {
 334 kkz      1.1                     for(int j = i+1; j < q.numSigmas(); j++) {
 335 cananian 1.4                         assert !q.src(j).equals(retval);
 336 kkz      1.1                     }
 337 kkz      1.1                     // handle normal return
 338 kkz      1.1                     if (i < q.numSigmas() && 
 339 kkz      1.1                         (retval == null || !retval.equals(q.retval())))
 340 kkz      1.1                         retval = q.dst(i, 0);
 341 kkz      1.1                     else
 342 kkz      1.1                         retval = null;
 343 kkz      1.1                     nParam = q.nextEdge(0).which_pred();
 344 kkz      1.1                     q.next(0).accept(this);
 345 kkz      1.1                     // handle exceptional return
 346 kkz      1.1                     if (i < q.numSigmas() &&
 347 kkz      1.1                         (retval == null || !retval.equals(q.retex())))
 348 kkz      1.1                         retval = q.dst(i, 1);
 349 kkz      1.1                     else
 350 kkz      1.1                         retval = null;
 351 kkz      1.1                     nParam = q.nextEdge(1).which_pred();
 352 kkz      1.1                     q.next(1).accept(this);
 353 kkz      1.1                     break;
 354 kkz      1.1                 }
 355 kkz      1.1             }
 356 kkz      1.1         }
 357 kkz      1.1 
 358 kkz      1.1         public void visit(Quad q) {
 359 kkz      1.1             if (q.nextLength() != 0) {
 360 cananian 1.4                 assert q.nextLength() == 1 : q;
 361 kkz      1.1                 if (q.defC().contains(retval))
 362 kkz      1.1                     retval = null;
 363 kkz      1.1                 nParam = q.nextEdge(0).which_pred();
 364 kkz      1.1                 q.next(0).accept(this);
 365 kkz      1.1             }
 366 kkz      1.1         }
 367 kkz      1.1 
 368 kkz      1.1         public void visit(PHI q) {
 369 kkz      1.1             for(int i = 0; i < q.numPhis(); i++) {
 370 kkz      1.1                 if (q.src(i, nParam).equals(retval)) {
 371 kkz      1.1                     for(int j = i+1; j < q.numPhis(); j++) {
 372 cananian 1.4                         assert !q.src(j, nParam).equals(retval);
 373 kkz      1.1                     }
 374 kkz      1.1                     if (done.containsKey(q)) {
 375 kkz      1.1                         // already handled once, check correctness
 376 cananian 1.4                         assert q.dst(i).equals(done.get(q));
 377 kkz      1.1                     } else {
 378 kkz      1.1                         retval = q.dst(i);
 379 kkz      1.1                         done.put(q, retval);
 380 cananian 1.4                         assert q.nextLength() == 1;
 381 kkz      1.1                         nParam = q.nextEdge(0).which_pred();
 382 kkz      1.1                         q.next(0).accept(this);
 383 kkz      1.1                     }
 384 kkz      1.1                     return;
 385 kkz      1.1                 }
 386 kkz      1.1             }
 387 kkz      1.1             // in some cases, we may have to add a phi function to the PHI
 388 kkz      1.1             if (done.containsKey(q) && !retval.equals(done.get(q))) {
 389 cananian 1.4                 assert retval != null;
 390 kkz      1.1                 Tuple tup = (Tuple) done.get(q);
 391 kkz      1.1                 Temp[] retvals = (Temp[]) tup.proj(0);
 392 kkz      1.1                 int count = ((Integer) tup.proj(1)).intValue();
 393 kkz      1.1                 if (count == q.arity()-1) {
 394 kkz      1.1                     // fix-up PHI
 395 kkz      1.1                     Temp dst[] = new Temp[q.numPhis()+1];
 396 kkz      1.1                     Temp src[][] = new Temp[q.numPhis()+1][];
 397 kkz      1.1                     for(int i = 0; i < q.numPhis(); i++)
 398 kkz      1.1                         dst[i] = q.dst(i);
 399 kkz      1.1                     // new destination Temp
 400 kkz      1.1                     dst[dst.length-1] = new Temp(q.getFactory().tempFactory());
 401 kkz      1.1                     for(int i = 0; i < q.numPhis(); i++)
 402 kkz      1.1                         src[i] = q.src(i);
 403 kkz      1.1                     retvals[nParam] = retval;
 404 kkz      1.1                     src[src.length-1] = retvals;
 405 kkz      1.1                     PHI phi = new PHI(q.getFactory(), q, dst, src, q.arity());
 406 kkz      1.1                     Quad.replace(q, phi);
 407 kkz      1.1                     retval = dst[dst.length-1];
 408 cananian 1.4                     assert phi.nextLength() == 1;
 409 kkz      1.1                     nParam = phi.nextEdge(0).which_pred();
 410 kkz      1.1                     phi.next(0).accept(this);
 411 kkz      1.1                 } else {
 412 kkz      1.1                     retvals[nParam] = retval;
 413 kkz      1.1                     done.put(q, new Tuple(new Object[] 
 414 kkz      1.1                                           { retvals, new Integer(count+1) }));
 415 kkz      1.1                 }
 416 kkz      1.1             } else {
 417 kkz      1.1                 Temp[] retvals = new Temp[q.arity()];
 418 cananian 1.4                 assert retval != null;
 419 kkz      1.1                 retvals[nParam] = retval;
 420 kkz      1.1                 done.put(q, new Tuple(new Object[] {retvals, new Integer(1)}));
 421 kkz      1.1             }
 422 kkz      1.1         }
 423 kkz      1.1 
 424 kkz      1.1         public void visit(RETURN q) {
 425 cananian 1.4             assert retval != null;
 426 kkz      1.1             RETURN nreturn = new RETURN(q.getFactory(), q, retval);
 427 kkz      1.1             Quad.replace(q, nreturn);
 428 kkz      1.1             // RETURNs only have one successor, the FOOTER node,
 429 kkz      1.1             // which we don't need to visit
 430 kkz      1.1         }
 431 kkz      1.1 
 432 kkz      1.1         public void visit(SIGMA q) {
 433 kkz      1.1             for(int i = 0; i < q.numSigmas(); i++) {
 434 kkz      1.1                 if (q.src(i).equals(retval)) {
 435 kkz      1.1                     for(int j = i+1; j < q.numSigmas(); j++) {
 436 cananian 1.4                         assert !q.src(j).equals(retval);
 437 kkz      1.1                     }
 438 kkz      1.1                     for(int k = 0; k < q.arity(); k++) {
 439 kkz      1.1                         retval = q.dst(i, k);
 440 kkz      1.1                         nParam = q.nextEdge(k).which_pred();
 441 kkz      1.1                         q.next(k).accept(this);
 442 kkz      1.1                     }
 443 kkz      1.1                     return;
 444 kkz      1.1                 }
 445 kkz      1.1             }
 446 cananian 1.4             assert false;
 447 kkz      1.1         }
 448 kkz      1.1     }
 449 kkz      1.1 
 450 kkz      1.1     /** private class for traversing the graph to find the
 451 kkz      1.1      *  straight-line code that needs to be moved.
 452 kkz      1.1      */
 453 kkz      1.1     private static class findChain extends QuadVisitor
 454 kkz      1.1     {
 455 kkz      1.1         Temp thisObj;
 456 kkz      1.1         Quad end; // last Quad that needs *this* before control flow split
 457 kkz      1.1 
 458 kkz      1.1         findChain(Temp thisObj, NEW nnew, CALL call) {
 459 kkz      1.1             this.thisObj = thisObj;
 460 kkz      1.1             for(int i = 0; i < call.numSigmas(); i++) {
 461 kkz      1.1                 if (call.src(i).equals(thisObj)) {
 462 kkz      1.1                     this.thisObj = call.dst(i, 0);
 463 kkz      1.1                     break;
 464 kkz      1.1                 }
 465 kkz      1.1             }
 466 kkz      1.1             // start with the Quad on the 0-edge (normal return)
 467 kkz      1.1             // of the call to the superclass constructor
 468 kkz      1.1             call.next(0).accept(this);
 469 kkz      1.1         }
 470 kkz      1.1 
 471 kkz      1.1         // done when we hit a control flow split
 472 kkz      1.1         public void visit(SIGMA q) {
 473 kkz      1.1             return;
 474 kkz      1.1         }
 475 kkz      1.1 
 476 kkz      1.1         public void visit(PHI q) {
 477 cananian 1.4             assert false : "Cannot be transformed.";
 478 kkz      1.1         }
 479 kkz      1.1 
 480 kkz      1.1         public void visit(Quad q) {
 481 kkz      1.1             if (q.useC().contains(thisObj))
 482 kkz      1.1                 end = q;
 483 cananian 1.4             assert q.nextLength() == 1 : "Unexpected Quad.";
 484 kkz      1.1             q.next(0).accept(this);
 485 kkz      1.1         }
 486 kkz      1.1     }
 487 kkz      1.1 
 488 kkz      1.1     /** private class for traversing the graph to find
 489 kkz      1.1      *  the <code>Temp</code>s used by a chain of
 490 kkz      1.1      *  straight-line code.
 491 kkz      1.1      */
 492 kkz      1.1     private static class findTemps extends QuadVisitor
 493 kkz      1.1     {
 494 kkz      1.1         Quad end; // last Quad
 495 kkz      1.1         CALL call;
 496 kkz      1.1         Set needs;
 497 kkz      1.1         Set gen;
 498 kkz      1.1         Set protect;
 499 kkz      1.1         Map tMap;
 500 kkz      1.1         boolean safe;
 501 kkz      1.1 
 502 kkz      1.1         findTemps(METHOD method, NEW nnew, CALL call, Quad end) {
 503 kkz      1.1             this.end = end;
 504 kkz      1.1             this.call = call;
 505 kkz      1.1             this.gen = new HashSet();
 506 kkz      1.1             this.needs = new HashSet();
 507 kkz      1.1             this.protect = new HashSet();
 508 kkz      1.1             this.tMap = new HashMap();
 509 kkz      1.1             this.safe = true;
 510 kkz      1.1             // handle NEW
 511 kkz      1.1             gen.add(nnew.dst());
 512 kkz      1.1             // handle CALL
 513 kkz      1.1             for(int i = 0; i < call.paramsLength(); i++) {
 514 kkz      1.1                 if (!gen.contains(call.params(0)))
 515 kkz      1.1                     needs.add(call.params(0));
 516 kkz      1.1             }
 517 kkz      1.1             gen.add(call.retval());
 518 kkz      1.1             // build protected set of Temps
 519 kkz      1.1             for(int i = 0; i < method.paramsLength(); i++) {
 520 kkz      1.1                 Temp t = method.params(i);
 521 kkz      1.1                 protect.add(t);
 522 kkz      1.1                 for(int j = 0; j < call.numSigmas(); j++) {
 523 kkz      1.1                     if (call.src(j).equals(t)) {
 524 kkz      1.1                         protect.remove(t);
 525 kkz      1.1                         protect.add(call.dst(j,0));
 526 kkz      1.1                         break;
 527 kkz      1.1                     }
 528 kkz      1.1                 }
 529 kkz      1.1             }
 530 kkz      1.1             // build mapping of Temps
 531 kkz      1.1             for(int i = 0; i < call.numSigmas(); i++) {
 532 kkz      1.1                 tMap.put(call.dst(i,0), call.src(i));
 533 kkz      1.1             }
 534 kkz      1.1             // start with the Quad on the 0-edge (normal return)
 535 kkz      1.1             // of the call to the superclass constructor
 536 kkz      1.1             call.next(0).accept(this);
 537 kkz      1.1         }
 538 kkz      1.1 
 539 kkz      1.1         // done when we hit a control flow split
 540 kkz      1.1         public void visit(SIGMA q) {
 541 cananian 1.4             assert false : "Invalid sequence.";
 542 kkz      1.1         }
 543 kkz      1.1 
 544 kkz      1.1         public void visit(PHI q) {
 545 cananian 1.4             assert false : "Invalid sequence.";
 546 kkz      1.1         }
 547 kkz      1.1 
 548 kkz      1.1         public void visit(Quad q) {
 549 cananian 1.5             for(Object tO : q.useC()) {
 550 cananian 1.5                 Temp t = (Temp) tO;
 551 kkz      1.1                 Temp m = (Temp) tMap.get(t);
 552 kkz      1.1                 t = (m == null) ? t : m;
 553 kkz      1.1                 if (!gen.contains(t))
 554 kkz      1.1                     needs.add(t);
 555 kkz      1.1             }
 556 cananian 1.5             for(Object tO : q.defC()) {
 557 cananian 1.5                 Temp t = (Temp) tO;
 558 kkz      1.1                 if (protect.contains(t)) {
 559 kkz      1.1                     safe = false;
 560 kkz      1.1                     return;
 561 kkz      1.1                 }
 562 kkz      1.1                 Temp m = (Temp) tMap.get(t);
 563 kkz      1.1                 t = (m == null) ? t : m;
 564 kkz      1.1                 gen.add(t);
 565 kkz      1.1             }
 566 cananian 1.4             assert q.nextLength() == 1 : "Unexpected Quad.";
 567 kkz      1.1             if (!q.equals(end))
 568 kkz      1.1                 q.next(0).accept(this);
 569 kkz      1.1         }
 570 kkz      1.1     }
 571 kkz      1.1 
 572 kkz      1.1     /** private class for traversing the graph as setup for 
 573 kkz      1.1      *  conversion to recursive form.
 574 kkz      1.1      */
 575 kkz      1.1     private static class checkDependencies extends QuadVisitor
 576 kkz      1.1     {
 577 kkz      1.1         Temp thisObj;
 578 kkz      1.1         Set phis;
 579 kkz      1.1         Set gen;
 580 kkz      1.1         boolean safe;
 581 kkz      1.1         int nParam;
 582 kkz      1.1 
 583 kkz      1.1         checkDependencies(METHOD method, NEW nnew, CALL call, Quad start) {
 584 kkz      1.1             this.gen = new HashSet();
 585 kkz      1.1             this.safe = true;
 586 kkz      1.1             this.phis = new HashSet();
 587 kkz      1.1             this.thisObj = nnew.dst();
 588 kkz      1.1             // map thisObj to appropriate post-call Temp
 589 kkz      1.1             for(int i = 0; i < call.numSigmas(); i++) {
 590 kkz      1.1                 if (call.src(i).equals(thisObj))
 591 kkz      1.1                     thisObj = call.dst(i, 0);
 592 kkz      1.1             }
 593 kkz      1.1             // assumes that the only available Temps are
 594 kkz      1.1             // the method parameters
 595 kkz      1.1             for(int i = 0; i < method.paramsLength(); i++) {
 596 kkz      1.1                 Temp t = method.params(i);
 597 kkz      1.1                 gen.add(t);
 598 kkz      1.1                 for(int j = 0; j < call.numSigmas(); j++) {
 599 kkz      1.1                     if (call.src(j).equals(t)) {
 600 kkz      1.1                         gen.remove(t);
 601 kkz      1.1                         gen.add(call.dst(j, 0));
 602 kkz      1.1                     }
 603 kkz      1.1                 }
 604 kkz      1.1             }
 605 kkz      1.1             // start with the next Quad
 606 cananian 1.4             assert start.nextLength() == 1;
 607 kkz      1.1             nParam = start.nextEdge(0).which_pred();
 608 kkz      1.1             start.next(0).accept(this);
 609 kkz      1.1         }
 610 kkz      1.1 
 611 kkz      1.1         public void visit(CALL q) {
 612 kkz      1.1             for(int i = 0; i < q.paramsLength(); i++) {
 613 kkz      1.1                 if (!gen.contains(q.params(i))) {
 614 kkz      1.1                     safe = false;
 615 kkz      1.3                     //System.out.println(q + " needs " + q.params(i));
 616 kkz      1.1                     return;
 617 kkz      1.1                 }
 618 kkz      1.1             }
 619 kkz      1.1             Temp savedThis = thisObj;
 620 kkz      1.1             Set savedGen = gen;
 621 kkz      1.1             for(int i = 0; i < q.arity(); i++) {
 622 kkz      1.1                 // fixup thisObj
 623 kkz      1.1                 for(int j = 0; j < q.numSigmas(); j++) {
 624 kkz      1.1                     if (q.src(j).equals(savedThis)) {
 625 kkz      1.1                         thisObj = q.dst(j, i);
 626 kkz      1.1                         break;
 627 kkz      1.1                     }
 628 kkz      1.1                 }
 629 kkz      1.1                 // fixup gen
 630 kkz      1.1                 gen = new HashSet();
 631 kkz      1.1                 if (i == 0) {
 632 kkz      1.1                     for(int j = 0; j < q.numSigmas(); j++) {
 633 kkz      1.1                         if (q.src(j).equals(q.retval())) {
 634 kkz      1.1                             gen.add(q.dst(j, 0));
 635 kkz      1.1                             break;
 636 kkz      1.1                         }
 637 kkz      1.1                     }
 638 kkz      1.1                 } else {
 639 cananian 1.4                     assert i == 1;
 640 kkz      1.1                     for(int j = 0; j < q.numSigmas(); j++) {
 641 kkz      1.1                         if (q.src(j).equals(q.retex())) {
 642 kkz      1.1                             gen.add(q.dst(j, 1));
 643 kkz      1.1                             break;
 644 kkz      1.1                         }
 645 kkz      1.1                     }
 646 kkz      1.1                 }
 647 cananian 1.5                 for(Object tO : savedGen) {
 648 cananian 1.5                     Temp t = (Temp) tO;
 649 kkz      1.1                     gen.add(t);
 650 kkz      1.1                     for(int j = 0; j < q.numSigmas(); j++) {
 651 kkz      1.1                         if (q.src(j).equals(t)) {
 652 kkz      1.1                             gen.remove(t);
 653 kkz      1.1                             gen.add(q.dst(j, i));
 654 kkz      1.1                         }
 655 kkz      1.1                     }
 656 kkz      1.1                 }
 657 kkz      1.1                 // go down this path
 658 kkz      1.1                 nParam = q.nextEdge(i).which_pred();
 659 kkz      1.1                 q.next(i).accept(this);
 660 kkz      1.1             }
 661 kkz      1.1         }
 662 kkz      1.1 
 663 kkz      1.1         public void visit(CJMP q) {
 664 kkz      1.1             if (!gen.contains(q.test())) {
 665 kkz      1.1                 safe = false;
 666 kkz      1.3                 //System.out.println(q + " needs " + q.test());
 667 kkz      1.1                 return;
 668 kkz      1.1             }
 669 kkz      1.1             visit((SIGMA)q);
 670 kkz      1.1         }
 671 kkz      1.1 
 672 kkz      1.1         public void visit(PCALL q) {
 673 cananian 1.4             assert false : "Unimplemented.";
 674 kkz      1.1         }
 675 kkz      1.1 
 676 kkz      1.1         public void visit(PHI q) {
 677 kkz      1.1             if (!phis.contains(q)) {
 678 kkz      1.1                 phis.add(q);
 679 kkz      1.1                 // fixup thisObj
 680 kkz      1.1                 for(int i = 0; i < q.numPhis(); i++) {
 681 kkz      1.1                     if (q.src(i, nParam).equals(thisObj))
 682 kkz      1.1                         thisObj = q.dst(i);
 683 kkz      1.1                 }
 684 kkz      1.1                 // fixup gen
 685 kkz      1.1                 Set savedGen = gen;
 686 kkz      1.1                 gen = new HashSet();
 687 cananian 1.5                 for(Object tO : savedGen) {
 688 cananian 1.5                     Temp t = (Temp) tO;
 689 kkz      1.1                     gen.add(t);
 690 kkz      1.1                     for(int i = 0; i < q.numPhis(); i++) {
 691 kkz      1.1                         if (q.src(i, nParam).equals(t)) {
 692 kkz      1.1                             gen.remove(t);
 693 kkz      1.1                             gen.add(q.dst(i));
 694 kkz      1.1                         }
 695 kkz      1.1                     }
 696 kkz      1.1                 }
 697 cananian 1.4                 assert q.nextLength() == 1;
 698 kkz      1.1                 nParam = q.nextEdge(0).which_pred();
 699 kkz      1.1                 q.next(0).accept(this);
 700 kkz      1.1             }
 701 kkz      1.1         }
 702 kkz      1.1 
 703 kkz      1.1         public void visit(Quad q) {
 704 kkz      1.1             // check dependencies
 705 cananian 1.5             for(Object tO : q.useC()) {
 706 cananian 1.5                 Temp t = (Temp) tO;
 707 kkz      1.1                 if (!gen.contains(t) && !t.equals(thisObj)) {
 708 kkz      1.3                     //System.out.println(thisObj);
 709 kkz      1.1                     safe = false;
 710 kkz      1.3                     //System.out.println(q + " needs " + t);
 711 kkz      1.1                     return;
 712 kkz      1.1                 }
 713 kkz      1.1             }
 714 kkz      1.1             // add defs
 715 kkz      1.1             for(Iterator it = q.defC().iterator(); it.hasNext(); ) {
 716 kkz      1.1                 gen.add(it.next());
 717 kkz      1.1             }
 718 kkz      1.1             if (q.nextLength() == 0) return;
 719 cananian 1.4             assert q.nextLength() == 1;
 720 kkz      1.1             nParam = q.nextEdge(0).which_pred();
 721 kkz      1.1             q.next(0).accept(this);
 722 kkz      1.1         }
 723 kkz      1.1 
 724 kkz      1.1         public void visit(SIGMA q) {
 725 kkz      1.1             Temp savedThis = thisObj;
 726 kkz      1.1             Set savedGen = gen;
 727 kkz      1.1             for(int i = 0; i < q.arity(); i++) {
 728 kkz      1.1                 // fixup thisObj
 729 kkz      1.1                 for(int j = 0; j < q.numSigmas(); j++) {
 730 kkz      1.1                     if (q.src(j).equals(savedThis)) {
 731 kkz      1.1                         thisObj = q.dst(j, i);
 732 kkz      1.1                         break;
 733 kkz      1.1                     }
 734 kkz      1.1                 }
 735 kkz      1.1                 // fixup gen
 736 kkz      1.1                 gen = new HashSet();
 737 cananian 1.5                 for(Object tO : savedGen) {
 738 cananian 1.5                     Temp t = (Temp) tO;
 739 kkz      1.1                     gen.add(t);
 740 kkz      1.1                     for(int j = 0; j < q.numSigmas(); j++) {
 741 kkz      1.1                         if (q.src(j).equals(t)) {
 742 kkz      1.1                             gen.remove(t);
 743 kkz      1.1                             gen.add(q.dst(j, i));
 744 kkz      1.1                         }
 745 kkz      1.1                     }
 746 kkz      1.1                 }
 747 kkz      1.1                 // go down this path
 748 kkz      1.1                 nParam = q.nextEdge(i).which_pred();
 749 kkz      1.1                 q.next(i).accept(this);
 750 kkz      1.1             }
 751 kkz      1.1         }
 752 kkz      1.1 
 753 kkz      1.1         public void visit(SWITCH q) {
 754 cananian 1.4             assert false : "Unimplemented.";
 755 kkz      1.1         }
 756 kkz      1.1 
 757 kkz      1.1         public void visit(TYPESWITCH q) {
 758 cananian 1.4             assert false : "Unimplemented.";
 759 kkz      1.1         }
 760 kkz      1.1     }
 761 kkz      1.1 
 762 kkz      1.1     /** private class for traversing the graph for 
 763 kkz      1.1      *  conversion to recursive form.
 764 kkz      1.1      */
 765 kkz      1.1     private static class updateDependencies extends QuadVisitor
 766 kkz      1.1     {
 767 kkz      1.1         PHI lastPhi;
 768 kkz      1.1         Map phiMap;
 769 kkz      1.1         int nParam;
 770 kkz      1.1         Quad insertPt;
 771 kkz      1.1         Map insertPts;
 772 kkz      1.1         Map tMap;
 773 kkz      1.1         HMethod hm;
 774 kkz      1.1 
 775 kkz      1.1         updateDependencies(METHOD method, NEW nnew, CALL call, Quad start,
 776 kkz      1.1                            HMethod hm) {
 777 kkz      1.1             this.insertPts = new HashMap();
 778 kkz      1.1             this.phiMap = new HashMap();
 779 kkz      1.1             this.tMap = new HashMap();
 780 kkz      1.1             this.hm = hm;
 781 kkz      1.1             // create map needed for updating Quads
 782 kkz      1.1             // using post-call Temps to correct pre-call Temps
 783 kkz      1.1             for(int i = 0; i < method.paramsLength(); i++) {
 784 kkz      1.1                 Temp t = method.params(i);
 785 kkz      1.1                 for(int j = 0; j < call.numSigmas(); j++) {
 786 kkz      1.1                     tMap.put(call.dst(j, 0), call.src(j));
 787 kkz      1.1                 }
 788 kkz      1.1             }
 789 kkz      1.1             // start with the next Quad
 790 cananian 1.4             assert start.nextLength() == 1;
 791 kkz      1.1             nParam = start.nextEdge(0).which_pred();
 792 kkz      1.1             //start.next(0).accept(this);
 793 kkz      1.1             call.next(0).accept(this);
 794 kkz      1.1         }
 795 kkz      1.1 
 796 kkz      1.1         public void visit(CALL q) {
 797 kkz      1.3             //System.out.println(insertPt + " :: " + q);
 798 kkz      1.1             if (q.method().equals(hm))
 799 kkz      1.1                 insertPt = q;
 800 kkz      1.1             Temp[] oparams = q.params();
 801 kkz      1.1             Temp[] nparams = null;
 802 kkz      1.1             // remap params if necessary
 803 kkz      1.1             for(int i = 0; i < oparams.length; i++) {
 804 kkz      1.1                 if (tMap.containsKey(oparams[i])) {
 805 kkz      1.1                     if (nparams == null) {
 806 kkz      1.1                         nparams = new Temp[oparams.length];
 807 kkz      1.1                         System.arraycopy(oparams, 0, nparams, 0, 
 808 kkz      1.1                                          nparams.length);
 809 kkz      1.1                     }
 810 kkz      1.1                     nparams[i] = (Temp) tMap.get(oparams[i]);
 811 cananian 1.4                     assert nparams[i] != null;
 812 kkz      1.1                 }
 813 kkz      1.1             }
 814 kkz      1.1             Temp[] osrc = q.src();
 815 kkz      1.1             Temp[] nsrc = null;
 816 kkz      1.1             // remap sigma if needed
 817 kkz      1.1             for(int i = 0; i < q.numSigmas(); i++) {
 818 kkz      1.1                 if (tMap.containsKey(osrc[i])) {
 819 kkz      1.1                     if (nsrc == null) {
 820 kkz      1.1                         nsrc = new Temp[osrc.length];
 821 kkz      1.1                         System.arraycopy(osrc, 0, nsrc, 0, nsrc.length);
 822 kkz      1.1                     }
 823 kkz      1.1                     nsrc[i] = (Temp) tMap.get(osrc[i]);
 824 cananian 1.4                     assert nsrc[i] != null;
 825 kkz      1.1                 }
 826 kkz      1.1             }
 827 kkz      1.1             // replace call if necessary
 828 kkz      1.1             if (nparams != null || nsrc != null) {
 829 kkz      1.1                 nparams = (nparams == null) ? oparams : nparams;
 830 kkz      1.1                 nsrc = (nsrc == null) ? osrc : nsrc;
 831 kkz      1.1                 CALL ncall = new CALL(q.getFactory(), q, q.method(), 
 832 kkz      1.1                                          nparams, q.retval(), q.retex(),
 833 kkz      1.1                                          q.isVirtual(), q.isTailCall(),
 834 kkz      1.1                                          q.dst(), nsrc);
 835 kkz      1.1                 Quad.replace(q, ncall);
 836 kkz      1.1                 q = ncall;   
 837 kkz      1.1             }
 838 kkz      1.1             visit((SIGMA)q);
 839 kkz      1.1         }
 840 kkz      1.1 
 841 kkz      1.1         public void visit(CJMP q) {
 842 kkz      1.3             //System.out.println(insertPt + " :: " + q);
 843 kkz      1.1             Temp test = null;
 844 kkz      1.1             // remap test if needed
 845 kkz      1.1             if (tMap.containsKey(q.test())) {
 846 kkz      1.1                 test = (Temp) tMap.get(q.test());
 847 cananian 1.4                 assert test != null;
 848 kkz      1.1             }
 849 kkz      1.1             Temp[] osrc = q.src();
 850 kkz      1.1             Temp[] nsrc = null;
 851 kkz      1.1             // remap sigma if needed
 852 kkz      1.1             for(int i = 0; i < q.numSigmas(); i++) {
 853 kkz      1.1                 if (tMap.containsKey(osrc[i])) {
 854 kkz      1.1                     if (nsrc == null) {
 855 kkz      1.1                         nsrc = new Temp[osrc.length];
 856 kkz      1.1                         System.arraycopy(osrc, 0, nsrc, 0, nsrc.length);
 857 kkz      1.1                     }
 858 kkz      1.1                     nsrc[i] = (Temp) tMap.get(osrc[i]);
 859 cananian 1.4                     assert nsrc[i] != null;
 860 kkz      1.1                 }
 861 kkz      1.1             }
 862 kkz      1.1             if (test != null || nsrc != null) {
 863 kkz      1.1                 test = (test == null) ? q.test() : test;
 864 kkz      1.1                 nsrc = (nsrc == null) ? q.src() : nsrc;
 865 kkz      1.1                 CJMP ncjmp = new CJMP(q.getFactory(), q, test, q.dst(), nsrc);
 866 kkz      1.1                 Quad.replace(q, ncjmp);
 867 kkz      1.1                 q = ncjmp;
 868 kkz      1.1             }
 869 kkz      1.1             visit((SIGMA)q);
 870 kkz      1.1         }
 871 kkz      1.1 
 872 kkz      1.1         public void visit(FOOTER q) {
 873 kkz      1.3             //System.out.println(insertPt + " :: " + q);
 874 kkz      1.1             if (lastPhi != null && insertPt != null)
 875 kkz      1.1                 phiMap.put(lastPhi, insertPt);
 876 kkz      1.1         }
 877 kkz      1.1 
 878 kkz      1.1         public void visit(OPER q) {
 879 kkz      1.3             //System.out.println(insertPt + " :: " + q);
 880 kkz      1.1             // update operands if necessary
 881 kkz      1.1             Temp[] nt = null;
 882 kkz      1.1             Temp[] ot = q.operands();
 883 kkz      1.1             for(int i = 0; i < ot.length; i++) {
 884 kkz      1.1                 if (tMap.containsKey(ot[i])) {
 885 kkz      1.1                     if (nt == null) {
 886 kkz      1.1                         nt = new Temp[ot.length];
 887 kkz      1.1                         System.arraycopy(ot, 0, nt, 0, nt.length);
 888 kkz      1.1                     }
 889 kkz      1.1                     nt[i] = (Temp) tMap.get(ot[i]);
 890 cananian 1.4                     assert nt[i] != null;
 891 kkz      1.1                 }
 892 kkz      1.1             }
 893 kkz      1.1             // replace OPER if necessary
 894 kkz      1.1             if (nt != null) {
 895 kkz      1.1                 OPER noper = new OPER(q.getFactory(), q, q.opcode(), q.dst(), 
 896 kkz      1.1                                       nt);
 897 kkz      1.1                 Quad.replace(q, noper);
 898 kkz      1.1                 q = noper;
 899 kkz      1.1             }
 900 kkz      1.1             // update map if necessary
 901 kkz      1.1             tMap.remove(q.dst());
 902 cananian 1.4             assert q.nextLength() == 1;
 903 kkz      1.1             nParam = q.nextEdge(0).which_pred();
 904 kkz      1.1             q.next(0).accept(this);
 905 kkz      1.1         }
 906 kkz      1.1 
 907 kkz      1.1         public void visit(PCALL q) {
 908 cananian 1.4             assert false : "Unimplemented.";
 909 kkz      1.1         }
 910 kkz      1.1 
 911 kkz      1.1         public void visit(PHI q) {
 912 kkz      1.3             //System.out.println(insertPt + " :: " + q);
 913 kkz      1.1             // replace PHI if needed
 914 kkz      1.1             Temp[][] nsrc = null;
 915 kkz      1.1             for(int i = 0; i < q.numPhis(); i++) {
 916 kkz      1.1                 if (tMap.containsKey(q.src(i, nParam))) {
 917 kkz      1.1                     if (nsrc == null) {
 918 kkz      1.1                         nsrc = new Temp[q.numPhis()][];
 919 kkz      1.1                         for(int j = 0; j < nsrc.length; j++) {
 920 kkz      1.1                             nsrc[j] = new Temp[q.arity()];
 921 kkz      1.1                             System.arraycopy(q.src(i), 0, nsrc[j], 0, 
 922 kkz      1.1                                              nsrc[j].length);
 923 kkz      1.1                         }
 924 kkz      1.1                     nsrc[i][nParam] = (Temp) tMap.get(q.src(i, nParam));
 925 cananian 1.4                     assert nsrc[i][nParam] != null;
 926 kkz      1.1                     }
 927 kkz      1.1                 }
 928 kkz      1.1             }
 929 kkz      1.1             if (nsrc != null) {
 930 kkz      1.1                 Temp[] dst = new Temp[q.numPhis()];
 931 kkz      1.1                 for(int i = 0; i < dst.length; i++)
 932 kkz      1.1                     dst[i] = q.dst(i);
 933 kkz      1.1                 PHI phi = new PHI(q.getFactory(), q, dst, nsrc, q.arity());
 934 kkz      1.1                 Quad.replace(q, phi);
 935 kkz      1.1                 q = phi;
 936 kkz      1.1             }
 937 kkz      1.1             if (!phiMap.containsKey(q)) {
 938 kkz      1.1                 phiMap.put(q, null); // placeholder
 939 kkz      1.1                 lastPhi = q;
 940 kkz      1.1                 // fixup tMap
 941 kkz      1.1                 Map savedTMap = tMap;
 942 kkz      1.1                 tMap = new HashMap();
 943 cananian 1.5                 for(Object fromO : savedTMap.keySet()) {
 944 cananian 1.5                     Temp from = (Temp) fromO;
 945 kkz      1.1                     Temp to = (Temp) savedTMap.get(from);
 946 kkz      1.1                     tMap.put(from, to);
 947 kkz      1.1                     for(int i = 0; i < q.numPhis(); i++) {
 948 kkz      1.1                         if (q.src(i, nParam).equals(to))
 949 kkz      1.1                             tMap.put(from, q.dst(i));
 950 kkz      1.1                         if (q.src(i, nParam).equals(from))
 951 kkz      1.1                             tMap.put(from, null);
 952 kkz      1.1                     }
 953 kkz      1.1                 }
 954 cananian 1.4                 assert q.nextLength() == 1;
 955 kkz      1.1                 nParam = q.nextEdge(0).which_pred();
 956 kkz      1.1                 q.next(0).accept(this);
 957 kkz      1.1             } else {
 958 kkz      1.1                 Quad lastIP = (Quad) phiMap.get(q);
 959 kkz      1.1                 if (lastIP == null && insertPt != null) {
 960 kkz      1.1                     phiMap.put(q, insertPt);
 961 kkz      1.1                 }
 962 kkz      1.1             }
 963 kkz      1.1         }
 964 kkz      1.1 
 965 kkz      1.1         public void visit(Quad q) {
 966 kkz      1.3             //System.out.println(insertPt + " :: " + q);
 967 kkz      1.1             // we don't handle uses here
 968 cananian 1.4             assert q.useC().isEmpty();
 969 cananian 1.5             for(Object fromO : tMap.keySet()) {
 970 cananian 1.5                 Temp from = (Temp) fromO;
 971 kkz      1.1                 Temp to = (Temp) tMap.get(from);
 972 kkz      1.1                 if (q.defC().contains(from))
 973 kkz      1.1                     tMap.remove(from);
 974 kkz      1.1                 if (q.defC().contains(to))
 975 kkz      1.1                     tMap.put(from, null);
 976 kkz      1.1             }
 977 cananian 1.4             assert q.nextLength() == 1;
 978 kkz      1.1             nParam = q.nextEdge(0).which_pred();
 979 kkz      1.1             q.next(0).accept(this);
 980 kkz      1.1         }
 981 kkz      1.1 
 982 kkz      1.1         public void visit(RETURN q) {
 983 kkz      1.3             //System.out.println(insertPt + " :: " + q);
 984 kkz      1.1             if (tMap.containsKey(q.retval())) {
 985 kkz      1.1                 Temp t = (Temp) tMap.get(q.retval());
 986 cananian 1.4                 assert t != null;
 987 kkz      1.1                 RETURN nreturn = new RETURN(q.getFactory(), q, t);
 988 kkz      1.1                 Quad.replace(q, nreturn);
 989 kkz      1.1                 q = nreturn;
 990 kkz      1.1             }
 991 cananian 1.4             assert q.nextLength() == 1;
 992 kkz      1.1             nParam = q.nextEdge(0).which_pred();
 993 kkz      1.1             q.next(0).accept(this);
 994 kkz      1.1         }
 995 kkz      1.1 
 996 kkz      1.1         public void visit(SET q) {
 997 kkz      1.3             //System.out.println(insertPt + " :: " + q);
 998 kkz      1.1             // replace objectref if necessary
 999 kkz      1.1             Temp objectref = null;
1000 kkz      1.1             if (tMap.containsKey(q.objectref())) {
1001 kkz      1.1                 objectref = (Temp) tMap.get(q.objectref());
1002 cananian 1.4                 assert objectref != null;;
1003 kkz      1.1             }
1004 kkz      1.1             // replace src if necessary
1005 kkz      1.1             Temp src = null;
1006 kkz      1.1             if (tMap.containsKey(q.src())) {
1007 kkz      1.1                 src = (Temp) tMap.get(q.src());
1008 cananian 1.4                 assert src != null;
1009 kkz      1.1             }
1010 kkz      1.1             // replace SET if necessary
1011 kkz      1.1             if (objectref != null || src != null) {
1012 kkz      1.1                 objectref = (objectref == null) ? q.objectref() : objectref;
1013 kkz      1.1                 src = (src == null) ? q.src() : src;
1014 kkz      1.1                 SET set = new SET(q.getFactory(), q, q.field(), objectref, 
1015 kkz      1.1                                   src);
1016 kkz      1.1                 Quad.replace(q, set);
1017 kkz      1.1                 q = set;
1018 kkz      1.1             }
1019 cananian 1.4             assert q.nextLength() == 1;
1020 kkz      1.1             nParam = q.nextEdge(0).which_pred();
1021 kkz      1.1             q.next(0).accept(this);
1022 kkz      1.1         }
1023 kkz      1.1 
1024 kkz      1.1         public void visit(SIGMA q) {
1025 kkz      1.3             //System.out.println(insertPt + " :: " + q);
1026 kkz      1.1             Quad savedIP = insertPt;
1027 cananian 1.4             assert savedIP == null || savedIP.equals(q);
1028 kkz      1.1             Quad[] savedIPs = new Quad[q.arity()];
1029 kkz      1.1             Map savedTMap = tMap;
1030 kkz      1.1             PHI savedPhi = lastPhi; 
1031 kkz      1.1             for(int i = 0; i < q.arity(); i++) {
1032 kkz      1.1                 // fixup tMap
1033 kkz      1.1                 tMap = new HashMap();
1034 cananian 1.5                 for(Object fromO : savedTMap.keySet()) {
1035 cananian 1.5                     Temp from = (Temp) fromO;
1036 kkz      1.1                     Temp to = (Temp) savedTMap.get(from);
1037 kkz      1.1                     tMap.put(from, to);
1038 kkz      1.1                     if (q.kind() == QuadKind.CALL) {
1039 kkz      1.1                         if (i == 0 && to.equals(((CALL)q).retval())) {
1040 kkz      1.1                             tMap.put(from, null);
1041 kkz      1.1                             continue;
1042 kkz      1.1                         }
1043 kkz      1.1                         if (i == 1 && to.equals(((CALL)q).retex())) {
1044 kkz      1.1                             tMap.put(from, null);
1045 kkz      1.1                             continue;
1046 kkz      1.1                         }
1047 kkz      1.1                     }
1048 kkz      1.1                     for(int j = 0; j < q.numSigmas(); j++) {
1049 kkz      1.1                         // if Temp needs remapping, do so
1050 kkz      1.1                         if (q.src(j).equals(to))
1051 kkz      1.1                             tMap.put(from, q.dst(j, i));
1052 kkz      1.1                         // if Temp is being overwritten, flag
1053 kkz      1.1                         if (q.src(j).equals(from)) 
1054 kkz      1.1                             tMap.put(from, null);
1055 kkz      1.1                     }
1056 kkz      1.1                 }
1057 kkz      1.1                 insertPt = null;
1058 kkz      1.1                 // fixup lastPhi
1059 kkz      1.1                 lastPhi = savedPhi;
1060 kkz      1.1                 // go down this path
1061 kkz      1.1                 nParam = q.nextEdge(i).which_pred();
1062 kkz      1.1                 q.next(i).accept(this);
1063 kkz      1.1                 // check what we got from this path
1064 kkz      1.1                 savedIPs[i] = insertPt;
1065 kkz      1.1             }
1066 kkz      1.1             boolean all_null = true;
1067 kkz      1.1             for(int i = 0; i < q.arity(); i++) {
1068 kkz      1.1                 if (savedIPs[i] != null) {
1069 kkz      1.1                     all_null = false;
1070 kkz      1.1                     break;
1071 kkz      1.1                 }
1072 kkz      1.1             }
1073 kkz      1.1             if (!all_null || savedIP != null) {
1074 kkz      1.1                 insertPts.put(q, savedIPs);
1075 kkz      1.1                 insertPt = q;
1076 kkz      1.1             }
1077 kkz      1.1         }
1078 kkz      1.1 
1079 kkz      1.1         public void visit(SWITCH q) {
1080 cananian 1.4             assert false : "Unimplemented.";
1081 kkz      1.1         }
1082 kkz      1.1 
1083 kkz      1.1         public void visit(THROW q) {
1084 kkz      1.3             //System.out.println(insertPt + " :: " + q);
1085 kkz      1.1             if (tMap.containsKey(q.throwable())) {
1086 kkz      1.1                 Temp t = (Temp) tMap.get(q.throwable());
1087 cananian 1.4                 assert t != null;
1088 kkz      1.1                 THROW nthrow = new THROW(q.getFactory(), q, t);
1089 kkz      1.1                 Quad.replace(q, nthrow);
1090 kkz      1.1                 q = nthrow;
1091 kkz      1.1             }
1092 cananian 1.4             assert q.nextLength() == 1;
1093 kkz      1.1             nParam = q.nextEdge(0).which_pred();
1094 kkz      1.1             q.next(0).accept(this);
1095 kkz      1.1         }
1096 kkz      1.1 
1097 kkz      1.1         public void visit(TYPESWITCH q) {
1098 cananian 1.4             assert false : "Unimplemented.";
1099 kkz      1.1         }
1100 kkz      1.1     }
1101 kkz      1.1 
1102 kkz      1.1     /** private class for traversing the graph to convert 
1103 kkz      1.1      *  to recursive form.
1104 kkz      1.1      */
1105 kkz      1.1     private static class makeRecurse extends QuadVisitor
1106 kkz      1.1     {
1107 kkz      1.1         Map quad2quadA;
1108 kkz      1.1         NEW begin;
1109 kkz      1.1         Temp thisObj;
1110 kkz      1.1         Set news = new HashSet();
1111 kkz      1.1 
1112 kkz      1.1         makeRecurse(Map quad2quadA, NEW begin) {
1113 kkz      1.1             this.quad2quadA = quad2quadA;
1114 kkz      1.1             // prepare exception edge
1115 kkz      1.1             CALL ocall = (CALL) begin.next(0);
1116 kkz      1.1             // map receiver
1117 kkz      1.1             Map rcvrMap = (new mapTemp(begin.dst(), ocall.next(0),
1118 kkz      1.1                                        quad2quadA, 
1119 kkz      1.1                                        Collections.EMPTY_SET)).quad2temp;
1120 kkz      1.1             PHI phi = null;
1121 kkz      1.1             int ex_pred = 0;
1122 kkz      1.1             if (ocall.next(1).kind() == QuadKind.PHI) {
1123 kkz      1.1                 phi = (PHI) ocall.next(1);
1124 kkz      1.1                 ex_pred = phi.arity();
1125 kkz      1.1             }
1126 kkz      1.1             // move things
1127 cananian 1.5             for(Object sigmaO : quad2quadA.keySet()) {
1128 cananian 1.5                 SIGMA sigma = (SIGMA) sigmaO;
1129 kkz      1.1                 Quad[] value = (Quad[]) quad2quadA.get(sigma);
1130 kkz      1.1                 for(int i = 0; i < sigma.arity(); i++) {
1131 kkz      1.1                     if (sigma.kind() == QuadKind.CALL && i == 1)
1132 kkz      1.1                         // ignore exception edges
1133 kkz      1.1                         continue;
1134 kkz      1.1                     if (value[i] != null)
1135 kkz      1.1                         // look elsewhere
1136 kkz      1.1                         continue;
1137 kkz      1.1                     Temp rcvr = (Temp) rcvrMap.get(sigma);
1138 cananian 1.4                     assert rcvr != null : sigma;
1139 kkz      1.1                     TempFactory tf = begin.getFactory().tempFactory();
1140 kkz      1.1                     Temp rcvr0 = new Temp(tf);
1141 kkz      1.1                     NEW nnew = new NEW(begin.getFactory(), begin, rcvr0,
1142 kkz      1.1                                        begin.hclass());
1143 kkz      1.1                     news.add(nnew);
1144 kkz      1.1                     Temp retval = (ocall.retval() == null) ? null : 
1145 kkz      1.1                         new Temp(tf);
1146 kkz      1.1                     Temp retex = (ocall.retex() == null) ? null : 
1147 kkz      1.1                         new Temp(tf);
1148 kkz      1.1                     // find out if any sigmas need to be propagated
1149 kkz      1.1                     Temp[] dstSaved = new Temp[sigma.numSigmas()];
1150 kkz      1.1                     Temp[] dst0 = new Temp[sigma.numSigmas()];
1151 kkz      1.1                     int numSigmas = 0;
1152 kkz      1.1                     for(int j = 0; j < sigma.numSigmas(); j++) {
1153 kkz      1.1                         if (!sigma.dst(j, 0).equals(rcvr)) {
1154 kkz      1.1                             dstSaved[j] = sigma.dst(j, 0);
1155 kkz      1.1                             dst0[j] = new Temp(tf);
1156 kkz      1.1                             numSigmas++;
1157 kkz      1.1                         } else {
1158 kkz      1.1                             dst0[j] = sigma.dst(j, 0);
1159 kkz      1.1                         }
1160 kkz      1.1                     }
1161 kkz      1.1                     // fixup sigma
1162 kkz      1.1                     sigma.assign(dst0, 0);
1163 kkz      1.1                     // shrink src array to size
1164 kkz      1.1                     Temp[] src = new Temp[numSigmas+1];
1165 kkz      1.1                     src[0] = rcvr0;
1166 kkz      1.1                     for(int j = 0, k = 1; j < sigma.numSigmas(); j++) {
1167 kkz      1.1                         if (dstSaved[j] != null) {
1168 kkz      1.1                             src[k] = sigma.dst(j, 0);
1169 kkz      1.1                             k++;
1170 kkz      1.1                         }
1171 kkz      1.1                     }
1172 kkz      1.1                     Temp[][] dst = new Temp[numSigmas+1][];
1173 kkz      1.1                     dst[0] = new Temp[] { rcvr, new Temp(tf) };
1174 kkz      1.1                     for(int j = 0, k = 1; j < sigma.numSigmas(); j++) {
1175 kkz      1.1                         if (dstSaved[j] != null) {
1176 kkz      1.1                             dst[k] = new Temp[] { dstSaved[j], new Temp(tf) };
1177 kkz      1.1                             k++;
1178 kkz      1.1                         }
1179 kkz      1.1                     }
1180 kkz      1.1                     // make CALL
1181 kkz      1.1                     CALL ncall = new CALL(ocall.getFactory(), ocall, 
1182 kkz      1.1                                           ocall.method(), new Temp[] { rcvr0 },
1183 kkz      1.1                                           retval, retex, ocall.isVirtual(),
1184 kkz      1.1                                           ocall.isTailCall(), dst, src);
1185 kkz      1.3                     //System.out.println(ncall);
1186 kkz      1.1                     Quad.addEdge(ncall, 0, sigma.next(i), 
1187 kkz      1.1                                  sigma.nextEdge(i).which_pred());
1188 kkz      1.1                     Quad.addEdge(nnew, 0, ncall, 0);
1189 kkz      1.1                     Quad.addEdge(sigma, i, nnew, 0);
1190 kkz      1.1                     if (phi == null) {
1191 cananian 1.4                         assert retex != null;
1192 kkz      1.1                         Temp[][] srcs = new Temp[1][];
1193 kkz      1.1                         srcs[0] = new Temp[] { retex };
1194 kkz      1.1                         phi = new PHI(ocall.getFactory(), ocall, 
1195 kkz      1.1                                       new Temp[] { ocall.retex() }, srcs, 1);
1196 kkz      1.1                         Quad.addEdge(phi, 0, ocall.next(1), 
1197 kkz      1.1                                      ocall.nextEdge(1).which_pred());
1198 kkz      1.1                     } else {
1199 kkz      1.1                         phi = phi.grow(new Temp[] { retex }, ex_pred);
1200 kkz      1.1                     }
1201 kkz      1.1                     Quad.addEdge(ncall, 1, phi, ex_pred++);
1202 kkz      1.1                     // update value to point to new CALL
1203 kkz      1.1                     value[i] = ncall;
1204 kkz      1.1                 }
1205 kkz      1.1             }
1206 kkz      1.1             // further updates on quad2quadA
1207 kkz      1.1             for(Iterator it = news.iterator(); it.hasNext(); ) {
1208 kkz      1.1                 quad2quadA.put(((Quad)it.next()).next(0), 
1209 kkz      1.1                                new Quad[] { null, null });          
1210 kkz      1.1             }
1211 kkz      1.1             // hang on to METHOD
1212 kkz      1.1             METHOD method = (METHOD) begin.prev(0);
1213 kkz      1.1             // remove original NEW and CALL
1214 kkz      1.1             if (ocall.next(1) != null & ocall.next(1).kind() == QuadKind.PHI)
1215 kkz      1.1                 phi = phi.shrink(ocall.nextEdge(1).which_pred());
1216 kkz      1.1             Quad.addEdge(begin.prev(0), begin.prevEdge(0).which_succ(),
1217 kkz      1.1                          ocall.next(0), ocall.nextEdge(0).which_pred());
1218 kkz      1.1             // start updating other Quads
1219 kkz      1.1             this.thisObj = begin.dst();
1220 kkz      1.1             
1221 kkz      1.1             //method.next(0).accept(this);
1222 kkz      1.1         }
1223 kkz      1.1 
1224 kkz      1.1         public void visit(SET q) {
1225 kkz      1.1             //System.out.println("VISITING: " + q);
1226 kkz      1.1             if (q.objectref() != null && q.objectref().equals(thisObj)) {
1227 kkz      1.1                 // need to move this SET to the right place
1228 kkz      1.1                 //System.out.println("Making srcMap");
1229 kkz      1.1                 Map rcvrMap = (new mapTemp(thisObj, q, quad2quadA,
1230 kkz      1.1                                            news)).quad2temp;
1231 kkz      1.1                 Map srcMap = (new mapTemp(q.src(), q, quad2quadA,
1232 kkz      1.1                                           Collections.EMPTY_SET)).quad2temp;
1233 kkz      1.1                 // HACK! repeat to make sure the Quads don't change
1234 kkz      1.1                 rcvrMap = (new mapTemp(thisObj, q, quad2quadA, 
1235 kkz      1.1                                        news)).quad2temp;
1236 cananian 1.5                 for(Object sigmaO : quad2quadA.keySet()) {
1237 cananian 1.5                     SIGMA sigma = (SIGMA) sigmaO;
1238 kkz      1.1                     Quad[] value = (Quad[]) quad2quadA.get(sigma);
1239 kkz      1.1                     for(int i = 0; i < sigma.arity(); i++) {
1240 kkz      1.1                         if (sigma.kind() == QuadKind.CALL && i == 1)
1241 kkz      1.1                             // ignore exception edges
1242 kkz      1.1                             continue;
1243 kkz      1.1                         if (value[i] != null && 
1244 kkz      1.1                             value[i].kind() != QuadKind.SET)
1245 kkz      1.1                             // look elsewhere
1246 kkz      1.1                             continue;
1247 kkz      1.1                         Temp rcvr = (Temp) rcvrMap.get(sigma);
1248 cananian 1.4                         assert rcvr != null : sigma;
1249 kkz      1.1                         Temp src = (Temp) srcMap.get(sigma);
1250 kkz      1.1                         //System.out.println("Printing srcMap");
1251 kkz      1.1                         SET set = new SET(q.getFactory(), q, q.field(), rcvr,
1252 kkz      1.1                                           src);
1253 kkz      1.1                         if (value[i] == null) {
1254 kkz      1.1                             // attaching right after CALL
1255 kkz      1.1                             Quad.addEdge(set, 0, sigma.next(0),
1256 kkz      1.1                                          sigma.nextEdge(0).which_pred());
1257 kkz      1.1                             Quad.addEdge(sigma, 0, set, 0);
1258 kkz      1.1                         } else {
1259 kkz      1.1                             // attaching after another SET
1260 kkz      1.1                             Quad.addEdge(set, 0, value[i].next(0), 
1261 kkz      1.1                                          value[i].nextEdge(0).which_pred());
1262 kkz      1.1                             Quad.addEdge(value[i], 0, set, 0);
1263 kkz      1.1                         }
1264 kkz      1.1                         // modify value
1265 kkz      1.1                         value[i] = set;
1266 kkz      1.1                     }
1267 kkz      1.1                 }
1268 kkz      1.1                 // remove original SET
1269 kkz      1.1                 Quad next = q.next(0);
1270 kkz      1.1                 q.remove();
1271 kkz      1.1                 next.accept(this);
1272 kkz      1.1             } else {
1273 kkz      1.1                 // irrelevant SET, just continue
1274 cananian 1.4                 assert !q.useC().contains(thisObj);
1275 kkz      1.1                 q.next(0).accept(this);
1276 kkz      1.1             }
1277 kkz      1.1         }
1278 kkz      1.1 
1279 kkz      1.1         public void visit(NEW q) {
1280 kkz      1.1             //      System.out.println("VISITING: " + q);
1281 kkz      1.1             // only continue if this isn't one of the NEWs we added
1282 kkz      1.1             if (!news.contains(q))
1283 kkz      1.1                 q.next(0).accept(this);
1284 kkz      1.1         }
1285 kkz      1.1 
1286 kkz      1.1         public void visit(Quad q) {
1287 kkz      1.1             //      System.out.println("VISITING: " + q);
1288 kkz      1.1             // should not be referring to the receiver
1289 cananian 1.4             assert !q.useC().contains(thisObj);
1290 cananian 1.4             assert q.nextLength() == 1 && q.prevLength() == 1 : q;
1291 kkz      1.1             q.next(0).accept(this);
1292 kkz      1.1         }
1293 kkz      1.1 
1294 kkz      1.1         public void visit(SIGMA q) {
1295 kkz      1.1             //      System.out.println("VISITING: " + q);
1296 kkz      1.1             // only mapped sigmas should get here
1297 cananian 1.4             assert quad2quadA.containsKey(q);
1298 kkz      1.1             Quad[] quadA = (Quad[]) quad2quadA.get(q);
1299 kkz      1.1             int nSigma = q.numSigmas();
1300 kkz      1.1             // find sigma function for thisObj
1301 kkz      1.1             for(int i = 0; i < q.numSigmas(); i++) {
1302 kkz      1.1                 if (q.src(i).equals(thisObj)) {
1303 kkz      1.1                     nSigma = i;
1304 kkz      1.1                     break;
1305 kkz      1.1                 }
1306 kkz      1.1             }
1307 kkz      1.1             // go down branches
1308 kkz      1.1             Map savedQuad2QuadA = quad2quadA;
1309 kkz      1.1             for(int i = 0; i < q.arity(); i++) {
1310 kkz      1.1                 if (q.kind() == QuadKind.CALL && i == 1)
1311 kkz      1.1                     // skip exceptional branches
1312 kkz      1.1                     continue;
1313 kkz      1.1                 if (quadA[i] == null)
1314 kkz      1.1                     // skip, no need to look
1315 kkz      1.1                     continue;
1316 kkz      1.1                 quad2quadA = new HashMap();
1317 kkz      1.1                 if (quadA[i] != null && quadA[i].kind() != QuadKind.SET) {
1318 kkz      1.1                     Worklist toDo = new WorkSet();
1319 kkz      1.1                     toDo.push(quadA[i]);
1320 kkz      1.1                     while(!toDo.isEmpty()) {
1321 kkz      1.1                         SIGMA curr = (SIGMA) toDo.pull();
1322 kkz      1.1                         Quad[] value = (Quad[]) savedQuad2QuadA.remove(curr);
1323 cananian 1.4                         assert value != null : curr;
1324 kkz      1.1                         quad2quadA.put(curr, value);
1325 kkz      1.1                         for(int j = 0; j < value.length; j++) {
1326 kkz      1.1                             if (value[j] != null && 
1327 kkz      1.1                                 value[j].kind() != QuadKind.SET) {
1328 kkz      1.1                                 toDo.push(value[j]);
1329 kkz      1.1                             }
1330 kkz      1.1                         }
1331 kkz      1.1                     }
1332 kkz      1.1                 }
1333 kkz      1.1                 // setup thisObj
1334 kkz      1.1                 thisObj = (nSigma < q.numSigmas()) ? q.dst(nSigma, i) : null;
1335 kkz      1.1                 q.next(i).accept(this);
1336 kkz      1.1                 // fixup savedQuad2QuadA with possibly changed mappings
1337 kkz      1.1                 savedQuad2QuadA.putAll(quad2quadA);
1338 kkz      1.1             }
1339 kkz      1.1             // remove referencse to thisObj, if any
1340 kkz      1.1             if (nSigma < q.numSigmas()) {
1341 kkz      1.1                 // create new src array
1342 kkz      1.1                 Temp[] src = new Temp[q.numSigmas()-1];
1343 kkz      1.1                 for(int i = 0; i < q.numSigmas(); i++) {
1344 kkz      1.1                     if (i < nSigma)
1345 kkz      1.1                         src[i] = q.src(i);
1346 kkz      1.1                     else if (i > nSigma)
1347 kkz      1.1                         src[i-1] = q.src(i);
1348 kkz      1.1                 }
1349 kkz      1.1                 // create new dst array
1350 kkz      1.1                 Temp[][] dst = new Temp[q.numSigmas()-1][];
1351 kkz      1.1                 for(int i = 0; i < q.numSigmas(); i++) {
1352 kkz      1.1                     if (i < nSigma) {
1353 kkz      1.1                         dst[i] = new Temp[q.arity()];
1354 kkz      1.1                         System.arraycopy(q.dst(i), 0, dst[i], 0, q.arity());
1355 kkz      1.1                     } else if (i > nSigma) {
1356 kkz      1.1                         dst[i-1] = new Temp[q.arity()];
1357 kkz      1.1                         System.arraycopy(q.dst(i), 0, dst[i-1], 0, q.arity());
1358 kkz      1.1                     }
1359 kkz      1.1                 }
1360 kkz      1.1                 SIGMA nq = null;
1361 kkz      1.1                 if (q.kind() == QuadKind.CALL) {
1362 kkz      1.1                     CALL ocall = (CALL)q;
1363 kkz      1.1                     CALL ncall = new CALL(ocall.getFactory(), ocall, 
1364 kkz      1.1                                           ocall.method(), ocall.params(), 
1365 kkz      1.1                                           ocall.retval(), ocall.retex(),
1366 kkz      1.1                                           ocall.isVirtual(), 
1367 kkz      1.1                                           ocall.isTailCall(), dst, src);
1368 kkz      1.1                     nq = ncall;
1369 kkz      1.1                 } else {
1370 cananian 1.4                     assert q.kind() == QuadKind.CJMP;
1371 kkz      1.1                     CJMP ocjmp = (CJMP)q;
1372 kkz      1.1                     CJMP ncjmp = new CJMP(ocjmp.getFactory(), ocjmp, 
1373 kkz      1.1                                           ocjmp.test(), dst, src);
1374 kkz      1.1                     nq = ncjmp;
1375 kkz      1.1                 }
1376 kkz      1.1                 // link up new SIGMA
1377 kkz      1.1                 Quad.replace(q, nq);
1378 kkz      1.1                 // fix up quad2quadA
1379 kkz      1.1                 if (quad2quadA.containsKey(q))
1380 kkz      1.1                     quad2quadA.put(nq, quad2quadA.remove(q));
1381 cananian 1.5                 for(Object keyO : quad2quadA.keySet()) {
1382 cananian 1.5                     Quad key = (Quad) keyO;
1383 kkz      1.1                     Quad[] value = (Quad[]) quad2quadA.get(key);
1384 cananian 1.4                     assert value != null : key;
1385 kkz      1.1                     for(int j = 0; j < value.length; j++) {
1386 kkz      1.1                         if (q.equals(value[j]))
1387 kkz      1.1                             value[j] = nq;
1388 kkz      1.1                     }
1389 kkz      1.1                 }               
1390 kkz      1.1             }
1391 kkz      1.1         }
1392 kkz      1.1     }
1393 kkz      1.1 
1394 kkz      1.1     private static class mapTemp extends QuadVisitor
1395 kkz      1.1     {
1396 kkz      1.1         Map quad2temp;
1397 kkz      1.1         Temp target;
1398 kkz      1.1         Map quad2quadA;
1399 kkz      1.1         Set news;
1400 kkz      1.1 
1401 kkz      1.1         mapTemp(Temp target, Quad begin, Map quad2quadA, Set news) {
1402 kkz      1.1             this.news = news;
1403 kkz      1.1             this.target = target;
1404 kkz      1.1             this.quad2quadA = quad2quadA;
1405 kkz      1.1             this.quad2temp = new HashMap();
1406 kkz      1.1             begin.accept(this);
1407 kkz      1.1         }
1408 kkz      1.1 
1409 kkz      1.1         public void visit(NEW q) {
1410 kkz      1.1             // fixup for thisObj
1411 kkz      1.1             if (news.contains(q))
1412 kkz      1.1                 target = q.dst();
1413 kkz      1.1             q.next(0).accept(this);
1414 kkz      1.1         }
1415 kkz      1.1         
1416 kkz      1.1         public void visit(SIGMA q) {
1417 kkz      1.1             Temp savedTarget = target;
1418 kkz      1.1             // any SIGMA we visit should be mapped
1419 kkz      1.1             Quad[] quadA = (Quad[]) quad2quadA.get(q);
1420 cananian 1.4             assert quadA != null : q;
1421 kkz      1.1             for(int i = 0; i < q.arity(); i++) {
1422 kkz      1.1                 boolean found = false;
1423 kkz      1.1                 target = savedTarget;
1424 kkz      1.1                 for(int j = 0; j < q.numSigmas(); j++) {
1425 kkz      1.1                     //System.out.println(q.src(j) + " =? " + target);
1426 kkz      1.1                     if (q.src(j).equals(target)) {
1427 kkz      1.1                         target = q.dst(j, i);
1428 kkz      1.1                         // check for repeats
1429 kkz      1.1                         for(int k = j+1; k < q.numSigmas(); k++)
1430 cananian 1.4                             assert !q.src(k).equals(target);
1431 kkz      1.1                         found = true;
1432 kkz      1.1                         break;
1433 kkz      1.1                     }
1434 kkz      1.1                 }
1435 kkz      1.1                 if (q.kind() == QuadKind.CALL && i == 1) {
1436 kkz      1.1                     // exception edge, ignore
1437 kkz      1.1                     //target = savedTarget;
1438 kkz      1.1                     continue;
1439 kkz      1.1                 }
1440 kkz      1.1                 // may need to add sigma function
1441 kkz      1.1                 if (!found) {
1442 kkz      1.1                     //System.out.println("CANNOT FIND " + target);
1443 kkz      1.1                     //System.out.println(q + "\n");
1444 kkz      1.1                     Temp[][] dsts = new Temp[q.numSigmas()+1][];
1445 kkz      1.1                     for(int j = 0; j < q.numSigmas(); j++) {
1446 kkz      1.1                         Temp[] dst = new Temp[q.arity()];
1447 kkz      1.1                         System.arraycopy(q.dst(j), 0, dst, 0, dst.length);
1448 kkz      1.1                         dsts[j] = dst;
1449 kkz      1.1                     }
1450 kkz      1.1                     // add sigma function
1451 kkz      1.1                     dsts[dsts.length-1] = new Temp[q.arity()];
1452 kkz      1.1                     TempFactory tf = q.getFactory().tempFactory();
1453 kkz      1.1                     for(int j = 0; j < q.arity(); j++)
1454 kkz      1.1                         dsts[dsts.length-1][j] = new Temp(tf);
1455 kkz      1.1                     Temp[] src = new Temp[q.numSigmas()+1];
1456 kkz      1.1                     System.arraycopy(q.src(), 0, src, 0, src.length-1);
1457 kkz      1.1                     src[src.length-1] = target;
1458 kkz      1.1                     SIGMA nq = null;
1459 kkz      1.1                     if (q.kind() == QuadKind.CALL) {
1460 kkz      1.1                         CALL ocall = (CALL)q;
1461 kkz      1.1                         CALL ncall = new CALL(ocall.getFactory(), ocall,
1462 kkz      1.1                                               ocall.method(), ocall.params(),
1463 kkz      1.1                                               ocall.retval(), ocall.retex(),
1464 kkz      1.1                                               ocall.isVirtual(), 
1465 kkz      1.1                                               ocall.isTailCall(), dsts, src);
1466 kkz      1.1                         nq = ncall;
1467 kkz      1.1                     } else {
1468 cananian 1.4                         assert q.kind() == QuadKind.CJMP;
1469 kkz      1.1                         CJMP ocjmp = (CJMP)q;
1470 kkz      1.1                         CJMP ncjmp = new CJMP(ocjmp.getFactory(), ocjmp,
1471 kkz      1.1                                               ocjmp.test(), dsts, src);
1472 kkz      1.1                         nq = ncjmp;
1473 kkz      1.1                     }
1474 kkz      1.1                     // link up new Quad
1475 kkz      1.1                     Quad.replace(q, nq);
1476 kkz      1.1                     // fix up maps
1477 kkz      1.1                     quad2temp.remove(q);
1478 kkz      1.1                     if (quad2quadA.containsKey(q))
1479 kkz      1.1                         quad2quadA.put(nq, quad2quadA.remove(q));
1480 cananian 1.5                     for(Object keyO : quad2quadA.keySet()) {
1481 cananian 1.5                         Quad key = (Quad) keyO;
1482 kkz      1.1                         Quad[] value = (Quad[]) quad2quadA.get(key);
1483 kkz      1.1                         for(int j = 0; j < value.length; j++) {
1484 kkz      1.1                             if (q.equals(value[j]))
1485 kkz      1.1                                 value[j] = nq;
1486 kkz      1.1                         }
1487 kkz      1.1                     }           
1488 kkz      1.1                     q = nq;
1489 kkz      1.1                     target = q.dst(q.numSigmas()-1, i);
1490 kkz      1.1                     //System.out.println("MADE new " + q);
1491 kkz      1.1                     //System.out.println("Target is " + target);
1492 kkz      1.1                 }
1493 kkz      1.1                 //System.out.println("CHECKING "+quadA[i]);
1494 kkz      1.1                 if (quadA[i] != null && quadA[i].kind() != QuadKind.SET) {
1495 kkz      1.1                     // continue down this branch
1496 kkz      1.1                     //System.out.println("Continuing");
1497 kkz      1.1                     q.next(i).accept(this);
1498 kkz      1.1                 } else {
1499 kkz      1.1                     // end here
1500 kkz      1.1                     //System.out.println("adding entry");
1501 kkz      1.1                     quad2temp.put(q, target);
1502 kkz      1.1                 }
1503 kkz      1.1             }
1504 kkz      1.1         }
1505 kkz      1.1 
1506 kkz      1.1         public void visit(Quad q) {
1507 cananian 1.4             assert q.nextLength() == 1 && q.prevLength() == 1;
1508 kkz      1.1             q.next(0).accept(this);
1509 kkz      1.1         }
1510 kkz      1.1     }
1511 kkz      1.1 }
1512 kkz      1.1 
1513 kkz      1.1 
1514 kkz      1.1 
1515 kkz      1.1 
1516 kkz      1.1