1 kkz 1.1 // PointsToQuadVisitor.java, created Sat Jul 13 17:33:45 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.ClassFile.HClass; 7 kkz 1.1 import harpoon.ClassFile.HCode; 8 kkz 1.1 import harpoon.ClassFile.HCodeAndMaps; 9 kkz 1.1 import harpoon.ClassFile.HCodeFactory; 10 kkz 1.1 import harpoon.ClassFile.HConstructor; 11 kkz 1.1 import harpoon.ClassFile.HMethod; 12 kkz 1.1 import harpoon.ClassFile.Linker; 13 kkz 1.1 import harpoon.IR.Properties.CFGEdge; 14 kkz 1.1 import harpoon.IR.Quads.ANEW; 15 kkz 1.1 import harpoon.IR.Quads.ARRAYINIT; 16 kkz 1.1 import harpoon.IR.Quads.ASET; 17 kkz 1.1 import harpoon.IR.Quads.CALL; 18 kkz 1.1 import harpoon.IR.Quads.Code; 19 kkz 1.1 import harpoon.IR.Quads.Edge; 20 kkz 1.1 import harpoon.IR.Quads.FOOTER; 21 kkz 1.1 import harpoon.IR.Quads.HEADER; 22 kkz 1.1 import harpoon.IR.Quads.METHOD; 23 kkz 1.1 import harpoon.IR.Quads.MOVE; 24 kkz 1.1 import harpoon.IR.Quads.NEW; 25 kkz 1.1 import harpoon.IR.Quads.PHI; 26 kkz 1.1 import harpoon.IR.Quads.Quad; 27 kkz 1.1 import harpoon.IR.Quads.QuadFactory; 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.THROW; 32 kkz 1.1 import harpoon.Temp.Temp; 33 kkz 1.1 import harpoon.Util.Worklist; 34 kkz 1.1 import harpoon.Util.Collections.WorkSet; 35 kkz 1.1 36 kkz 1.1 import java.util.Collections; 37 kkz 1.1 import java.util.HashMap; 38 kkz 1.1 import java.util.HashSet; 39 kkz 1.1 import java.util.Iterator; 40 kkz 1.1 import java.util.Map; 41 kkz 1.1 import java.util.Set; 42 kkz 1.1 43 kkz 1.1 /** 44 kkz 1.1 * <code>PointsToQuadVisitor</code> performs local points to analysis, 45 kkz 1.1 * and can be subclassed for more specific purposes. 46 kkz 1.1 * 47 kkz 1.1 * @author Karen Zee <kkz@tmi.lcs.mit.edu> 48 kkz 1.1 * @version $Id: PointsToQuadVisitor.java,v 1.1 2002/07/18 21:06:00 kkz Exp $ */ 49 kkz 1.1 public class PointsToQuadVisitor extends harpoon.IR.Quads.QuadVisitor { 50 kkz 1.1 51 kkz 1.1 private final boolean DEBUG1 = false; 52 kkz 1.1 53 kkz 1.1 protected final Worklist toDo = new WorkSet(); 54 kkz 1.1 protected final Code code; 55 kkz 1.1 56 kkz 1.1 /** Creates a <code>PointsToQuadVisitor</code>. */ 57 kkz 1.1 public PointsToQuadVisitor(Code code) { 58 kkz 1.1 this.code = code; 59 kkz 1.1 } 60 kkz 1.1 61 kkz 1.1 // map of CFGEdges to aliases (Sets of Temps) 62 kkz 1.1 protected final Map EdgeToTemps = new HashMap(); 63 kkz 1.1 64 kkz 1.1 // Performs analysis with the given initial data flow fact for the 65 kkz 1.1 // entry point of the method. 66 kkz 1.1 protected void analyze(Set aliases) { 67 kkz 1.1 METHOD start = ((HEADER) code.getRootElement()).method(); 68 kkz 1.1 assert start.nextLength() == 1; 69 kkz 1.1 // initialize dataflow facts 70 kkz 1.1 EdgeToTemps.put(start.nextEdge(0), aliases); 71 kkz 1.1 // initialize to-do list 72 kkz 1.1 toDo.push(start.next(0)); 73 kkz 1.1 // go, gadget, go! 74 kkz 1.1 while(!toDo.isEmpty()) { 75 kkz 1.1 Quad q = (Quad) toDo.pull(); 76 kkz 1.1 if (DEBUG1) System.out.println(q); 77 kkz 1.1 q.accept(this); 78 kkz 1.1 } 79 kkz 1.1 } 80 kkz 1.1 81 kkz 1.1 public void visit(CALL q) { 82 kkz 1.1 assert q.prevLength() == 1; 83 kkz 1.1 Set aliases = get(q.prevEdge(0)); 84 kkz 1.1 // handle normal edge 85 kkz 1.1 Temp retval = q.retval(); 86 kkz 1.1 if (retval != null) 87 kkz 1.1 aliases.remove(retval); 88 kkz 1.1 handleSIGMAEdge(q, new HashSet(aliases), 0); 89 kkz 1.1 // handle exception edge 90 kkz 1.1 Temp retex = q.retex(); 91 kkz 1.1 if (retex != null) { 92 kkz 1.1 aliases.remove(retex); 93 kkz 1.1 // if retex == null, then the CALL has only 94 kkz 1.1 // one outgoing edge (only happens in quad- 95 kkz 1.1 // with-try), so only handle exception edge 96 kkz 1.1 // if retex != null 97 kkz 1.1 handleSIGMAEdge(q, new HashSet(aliases), 1); 98 kkz 1.1 } 99 kkz 1.1 } 100 kkz 1.1 101 kkz 1.1 public void visit(FOOTER q) { /* do nothing */ } 102 kkz 1.1 103 kkz 1.1 public void visit(MOVE q) { 104 kkz 1.1 assert q.prevLength() == 1 && q.nextLength() == 1; 105 kkz 1.1 Set aliases = new HashSet(get(q.prevEdge(0))); 106 kkz 1.1 if (aliases.contains(q.src())) 107 kkz 1.1 aliases.add(q.dst()); 108 kkz 1.1 else 109 kkz 1.1 aliases.remove(q.dst()); 110 kkz 1.1 raiseValue(q.nextEdge(0), aliases); 111 kkz 1.1 } 112 kkz 1.1 113 kkz 1.1 public void visit (PHI q) { 114 kkz 1.1 // start with the first non-null edge 115 kkz 1.1 int i; 116 kkz 1.1 Set aliases = null; 117 kkz 1.1 for (i = 0; i < q.arity(); i++) { 118 kkz 1.1 aliases = get(q.prevEdge(i)); 119 kkz 1.1 if (aliases != null) break; 120 kkz 1.1 } 121 kkz 1.1 if (aliases == null) { 122 kkz 1.1 raiseValue(q.nextEdge(0), null); 123 kkz 1.1 return; 124 kkz 1.1 } 125 kkz 1.1 Set renamed = new HashSet(aliases); 126 kkz 1.1 for (int j = 0 ; j < q.numPhis(); j++) { 127 kkz 1.1 // rename aliases as needed 128 kkz 1.1 Temp src = q.src(j, i); 129 kkz 1.1 // perform check on original set 130 kkz 1.1 // in case an alias has multiple 131 kkz 1.1 // renames 132 kkz 1.1 if (aliases.contains(src)) { 133 kkz 1.1 renamed.remove(src); 134 kkz 1.1 renamed.add(q.dst(j)); 135 kkz 1.1 } 136 kkz 1.1 } 137 kkz 1.1 // handle rest of edges 138 kkz 1.1 for (i = i+1 ; i < q.arity(); i++) { 139 kkz 1.1 aliases = get(q.prevEdge(i)); 140 kkz 1.1 if (aliases == null) continue; 141 kkz 1.1 Set renamed2 = new HashSet(aliases); 142 kkz 1.1 for(int j = 0; j < q.numPhis(); j++) { 143 kkz 1.1 // rename aliases as needed 144 kkz 1.1 Temp src = q.src(j, i); 145 kkz 1.1 // perform check on original set 146 kkz 1.1 // in case an alias has multiple 147 kkz 1.1 // renames 148 kkz 1.1 if (aliases.contains(src)) { 149 kkz 1.1 renamed2.remove(src); 150 kkz 1.1 renamed2.add(q.dst(j)); 151 kkz 1.1 } 152 kkz 1.1 } 153 kkz 1.1 // since this is a must analysis, 154 kkz 1.1 // we use set intersection: keep 155 kkz 1.1 // only if present in both sets 156 kkz 1.1 renamed.retainAll(renamed2); 157 kkz 1.1 } 158 kkz 1.1 raiseValue(q.nextEdge(0), renamed); 159 kkz 1.1 } 160 kkz 1.1 161 kkz 1.1 public void visit(Quad q) { 162 kkz 1.1 assert q.prevLength() == 1 && q.nextLength() == 1; 163 kkz 1.1 Set aliases = new HashSet(get(q.prevEdge(0))); 164 kkz 1.1 // remove redefined aliases, if any 165 kkz 1.1 aliases.removeAll(q.defC()); 166 kkz 1.1 raiseValue(q.nextEdge(0), aliases); 167 kkz 1.1 } 168 kkz 1.1 169 kkz 1.1 public void visit(SIGMA q) { 170 kkz 1.1 assert q.prevLength() == 1; 171 kkz 1.1 Set aliases = get(q.prevEdge(0)); 172 kkz 1.1 // iterate over successor edges 173 kkz 1.1 for(int i = 0; i < q.nextLength(); i++) 174 kkz 1.1 handleSIGMAEdge(q, new HashSet(aliases), i); 175 kkz 1.1 } 176 kkz 1.1 177 kkz 1.1 // retreive dataflow fact for CFGEdge e 178 kkz 1.1 protected Set get(CFGEdge e) { 179 kkz 1.1 Set V = (Set) EdgeToTemps.get(e); 180 kkz 1.1 if (DEBUG1) { 181 kkz 1.1 if (V == null) 182 kkz 1.1 System.out.println("\tget: {*}"); 183 kkz 1.1 else 184 kkz 1.1 System.out.println("\tget: " + V); 185 kkz 1.1 } 186 kkz 1.1 return V; 187 kkz 1.1 } 188 kkz 1.1 189 kkz 1.1 // update dataflow fact for CFGEdge e 190 kkz 1.1 protected void raiseValue(CFGEdge e, Set raised) { 191 kkz 1.1 if (DEBUG1) { 192 kkz 1.1 if (raised == null) 193 kkz 1.1 System.out.println("\traiseValue: {*}"); 194 kkz 1.1 else 195 kkz 1.1 System.out.println("\traiseValue: " + raised); 196 kkz 1.1 } 197 kkz 1.1 // add successor to to-do list, if necessary 198 kkz 1.1 if (!EdgeToTemps.containsKey(e)/*never processed before*/|| 199 kkz 1.1 !((Set) EdgeToTemps.get(e)).equals(raised)/*changed value*/) { 200 kkz 1.1 EdgeToTemps.put(e, raised); 201 kkz 1.1 toDo.push(e.to()); 202 kkz 1.1 } 203 kkz 1.1 } 204 kkz 1.1 205 kkz 1.1 // handleSIGMAEdge handles the index'th outgoing edge of the 206 kkz 1.1 // SIGMA q, given the set of aliases on the incoming edge 207 kkz 1.1 // requires: aliases be a Set of Temps 208 kkz 1.1 // modifies: aliases 209 kkz 1.1 protected void handleSIGMAEdge(SIGMA q, Set aliases, int index) { 210 kkz 1.1 Set insert = new HashSet(); 211 kkz 1.1 Set remove = new HashSet(); 212 kkz 1.1 // iterate over sigma functions 213 kkz 1.1 for(int j = 0; j < q.numSigmas(); j++) { 214 kkz 1.1 Temp src = q.src(j); 215 kkz 1.1 if (aliases.contains(src)) { 216 kkz 1.1 insert.add(q.dst(j, index)); 217 kkz 1.1 remove.add(src); 218 kkz 1.1 } 219 kkz 1.1 } 220 kkz 1.1 aliases.removeAll(remove); 221 kkz 1.1 aliases.addAll(insert); 222 kkz 1.1 raiseValue(q.nextEdge(index), aliases); 223 kkz 1.1 } 224 kkz 1.1 }