1 cananian 1.1.2.7 // LoopFinder.java, created Tue Jun 15 23:15:07 1999 by bdemsky 2 bdemsky 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 3 bdemsky 1.1.2.2 // Copyright 1999 by Brian Demsky 4 bdemsky 1.1.2.2 5 bdemsky 1.1.2.1 package harpoon.Analysis.Loops; 6 bdemsky 1.1.2.1 7 bdemsky 1.1.2.1 import harpoon.Analysis.Loops.Loops; 8 cananian 1.4 import net.cscott.jutil.WorkSet; 9 bdemsky 1.1.2.1 import harpoon.Analysis.DomTree; 10 bdemsky 1.1.2.1 import harpoon.ClassFile.HCode; 11 bdemsky 1.1.2.1 import harpoon.ClassFile.HCodeEdge; 12 bdemsky 1.1.2.1 import harpoon.ClassFile.HCodeElement; 13 pnkfelix 1.1.2.10 import harpoon.IR.Properties.CFGrapher; 14 bdemsky 1.1.2.1 import harpoon.Util.Util; 15 bdemsky 1.1.2.1 16 bdemsky 1.1.2.3 import java.util.Set; 17 pnkfelix 1.1.2.13 import java.util.Stack; 18 bdemsky 1.1.2.1 import java.util.Hashtable; 19 bdemsky 1.1.2.1 import java.util.Iterator; 20 bdemsky 1.1.2.1 /** 21 bdemsky 1.1.2.1 * <code>LoopFinder</code> implements Dominator Tree Loop detection. 22 bdemsky 1.1.2.1 * 23 bdemsky 1.1.2.5 * @author Brian Demsky <bdemsky@mit.edu> 24 cananian 1.5 * @version $Id: LoopFinder.java,v 1.5 2004/02/08 03:19:41 cananian Exp $ 25 bdemsky 1.1.2.1 */ 26 bdemsky 1.1.2.1 27 bdemsky 1.1.2.1 public class LoopFinder implements Loops { 28 bdemsky 1.1.2.5 29 cananian 1.1.2.9 DomTree dominator; 30 bdemsky 1.1.2.1 HCode hc,lasthc; 31 bdemsky 1.1.2.1 WorkSet setofloops; 32 bdemsky 1.1.2.1 Loop root; 33 bdemsky 1.1.2.1 Loop ptr; 34 pnkfelix 1.1.2.10 35 pnkfelix 1.1.2.10 CFGrapher grapher; 36 bdemsky 1.1.2.2 37 bdemsky 1.1.2.2 /** Creates a new LoopFinder object. 38 bdemsky 1.1.2.2 * This call takes an HCode and returns a LoopFinder object 39 bdemsky 1.1.2.2 * at the root level. Only use with Objects implementing the 40 cananian 1.1.2.8 * CFGraphable interface! 41 bdemsky 1.1.2.3 *<BR> <B> Requires: </B> <code> hc </code> is a <code> HCode</code> implementing 42 cananian 1.1.2.8 * the <code> CFGraphable </code> interface.*/ 43 bdemsky 1.1.2.5 44 bdemsky 1.1.2.1 public LoopFinder(HCode hc) { 45 pnkfelix 1.1.2.10 this(hc, CFGrapher.DEFAULT); 46 pnkfelix 1.1.2.10 } 47 pnkfelix 1.1.2.10 48 pnkfelix 1.1.2.10 49 pnkfelix 1.1.2.10 /** Creates a new LoopFinder object. 50 pnkfelix 1.1.2.10 * This call takes an HCode and a CFGrapher 51 pnkfelix 1.1.2.10 * and returns a LoopFinder object 52 pnkfelix 1.1.2.10 * at the root level. 53 pnkfelix 1.1.2.10 *<BR> <B> Requires: </B> <code> grapher </code> is a 54 pnkfelix 1.1.2.10 * <code>CFGrapher</code> for <code> hc </code>.*/ 55 pnkfelix 1.1.2.10 56 pnkfelix 1.1.2.10 public LoopFinder(HCode hc, CFGrapher grapher) { 57 pnkfelix 1.1.2.10 this.grapher = grapher; 58 bdemsky 1.1.2.5 this.hc=hc; 59 cananian 1.1.2.9 this.dominator=new DomTree(hc, false); 60 bdemsky 1.1.2.5 analyze(); 61 bdemsky 1.1.2.5 this.ptr=root; 62 bdemsky 1.1.2.1 } 63 pnkfelix 1.1.2.10 64 bdemsky 1.1.2.3 /**This method is for internal use only. 65 bdemsky 1.1.2.5 *It returns a Loopfinder object at any level, 66 bdemsky 1.1.2.5 *but it doesn't regenerate the internal tree 67 bdemsky 1.1.2.5 *so any external calls would result in garbage.*/ 68 bdemsky 1.1.2.5 69 cananian 1.1.2.11 private LoopFinder(HCode hc, CFGrapher grapher, DomTree dt, Loop root, Loop ptr) { 70 bdemsky 1.1.2.5 this.lasthc=hc; 71 cananian 1.1.2.11 this.grapher=grapher; 72 bdemsky 1.1.2.5 this.hc=hc; 73 cananian 1.1.2.9 this.dominator=dt; 74 bdemsky 1.1.2.5 this.root=root; 75 bdemsky 1.1.2.5 this.ptr=ptr; 76 bdemsky 1.1.2.1 } 77 bdemsky 1.1.2.5 78 bdemsky 1.1.2.1 /*-----------------------------*/ 79 bdemsky 1.1.2.5 80 bdemsky 1.1.2.3 /** This method returns the Root level loop for a given <code>HCode</code>. 81 bdemsky 1.1.2.5 * Does the same thing as the constructor call, but for an existing 82 bdemsky 1.1.2.5 * LoopFinder object.*/ 83 bdemsky 1.1.2.5 84 bdemsky 1.1.2.4 public Loops getRootloop(HCode hc) { 85 bdemsky 1.1.2.1 this.hc=hc; 86 bdemsky 1.1.2.1 analyze(); 87 cananian 1.1.2.11 return new LoopFinder(hc,grapher,dominator,root,root); 88 bdemsky 1.1.2.1 } 89 bdemsky 1.1.2.5 90 bdemsky 1.1.2.3 /** This method returns the entry point of the loop. 91 bdemsky 1.1.2.2 * For the natural loops we consider, that is simply the header. 92 cananian 1.1.2.11 * It returns a <code>Set</code> of <code>HCodeElement</code>s.*/ 93 bdemsky 1.1.2.5 94 bdemsky 1.1.2.4 public Set loopEntrances() { 95 cananian 1.1.2.12 WorkSet entries=new WorkSet(); 96 bdemsky 1.1.2.16 analyze(); 97 bdemsky 1.1.2.15 entries.push(ptr.header); 98 cananian 1.1.2.12 return entries; 99 cananian 1.1.2.12 } 100 bdemsky 1.1.2.16 101 cananian 1.1.2.12 public Set loopEntranceEdges() { 102 bdemsky 1.1.2.1 analyze(); 103 cananian 1.1.2.12 WorkSet A=new WorkSet(); 104 cananian 1.5 for (Object edgeO : grapher.predC(ptr.header)) { 105 cananian 1.5 HCodeEdge edge = (HCodeEdge) edgeO; 106 cananian 1.3 if (!ptr.entries.contains(edge.from())) 107 cananian 1.3 A.push(edge); 108 cananian 1.3 } 109 cananian 1.1.2.12 return A; 110 cananian 1.1.2.12 } 111 cananian 1.1.2.12 /** Returns a <code>Set</code> of all <code>HCodeElement</code>s 112 cananian 1.1.2.12 * in the loop which have an edge exiting the loop. */ 113 cananian 1.1.2.12 public Set loopExits() { 114 bdemsky 1.1.2.1 WorkSet entries=new WorkSet(); 115 cananian 1.5 for (Object hceO : loopExitEdges()) { 116 cananian 1.5 HCodeEdge hce = (HCodeEdge) hceO; 117 cananian 1.1.2.12 entries.push(hce.from()); 118 cananian 1.1.2.12 } 119 bdemsky 1.1.2.1 return entries; 120 bdemsky 1.1.2.1 } 121 cananian 1.1.2.12 /** Returns a <code>Set</code> of all <code>HCodeEdge</code>s 122 cananian 1.1.2.12 * exiting the loop. */ 123 cananian 1.1.2.12 public Set loopExitEdges() { 124 bdemsky 1.1.2.5 analyze(); 125 bdemsky 1.1.2.5 WorkSet A=new WorkSet(); 126 cananian 1.5 for (Object hceO : ptr.entries) { 127 cananian 1.5 HCodeElement hce = (HCodeElement) hceO; 128 cananian 1.5 for (Object edgeO : grapher.succC(hce)) { 129 cananian 1.5 HCodeEdge edge = (HCodeEdge) edgeO; 130 cananian 1.3 if (!ptr.entries.contains(edge.to())) 131 cananian 1.3 A.push(edge); 132 cananian 1.3 } 133 bdemsky 1.1.2.5 } 134 bdemsky 1.1.2.5 return A; 135 bdemsky 1.1.2.1 } 136 bdemsky 1.1.2.5 137 cananian 1.1.2.12 /** This method finds all of the backedges of the loop. 138 cananian 1.1.2.12 * Since we combine natural loops with the same header, this 139 cananian 1.1.2.12 * can be greater than one. This method returns a <code>Set</code> of 140 cananian 1.1.2.11 * <code>HCodeEdge</code>s.*/ 141 cananian 1.1.2.12 142 cananian 1.1.2.12 public Set loopBackEdges() { 143 bdemsky 1.1.2.5 analyze(); 144 bdemsky 1.1.2.5 WorkSet A=new WorkSet(); 145 cananian 1.5 for (Object hceO : ptr.entries) { 146 cananian 1.5 HCodeElement hce = (HCodeElement) hceO; 147 cananian 1.5 for (Object edgeO : grapher.succC(hce)) { 148 cananian 1.5 HCodeEdge edge = (HCodeEdge) edgeO; 149 cananian 1.3 if (edge.to()==ptr.header) 150 cananian 1.3 A.push(edge); 151 cananian 1.3 } 152 bdemsky 1.1.2.5 } 153 bdemsky 1.1.2.5 return A; 154 bdemsky 1.1.2.1 } 155 bdemsky 1.1.2.5 156 bdemsky 1.1.2.3 /**Returns a <code>Set</code> with all of the <code>HCodeElement</code>s of the loop and 157 bdemsky 1.1.2.5 *loops included entirely within this loop. */ 158 bdemsky 1.1.2.5 159 cananian 1.1.2.12 public Set loopIncElements() { 160 bdemsky 1.1.2.5 analyze(); 161 bdemsky 1.1.2.5 WorkSet A=new WorkSet(ptr.entries); 162 bdemsky 1.1.2.5 return A; 163 bdemsky 1.1.2.1 } 164 bdemsky 1.1.2.5 165 bdemsky 1.1.2.3 /** Returns all of the <code>HCodeElement</code>s of this loop that aren't in a nested 166 bdemsky 1.1.2.3 * loop. This returns a <code>Set</code> of <code>HCodeElement</code>s.*/ 167 bdemsky 1.1.2.5 168 cananian 1.1.2.12 public Set loopExcElements() { 169 bdemsky 1.1.2.5 analyze(); 170 bdemsky 1.1.2.5 WorkSet A=new WorkSet(ptr.entries); 171 bdemsky 1.1.2.5 WorkSet todo=new WorkSet(); 172 bdemsky 1.1.2.5 //Get the children 173 bdemsky 1.1.2.5 Iterator iterat=ptr.children.iterator(); 174 bdemsky 1.1.2.5 while (iterat.hasNext()) 175 bdemsky 1.1.2.5 todo.push(iterat.next()); 176 bdemsky 1.1.2.5 //Go down the tree 177 bdemsky 1.1.2.5 while(!todo.isEmpty()) { 178 bdemsky 1.1.2.5 Loop currptr=(Loop)todo.pop(); 179 bdemsky 1.1.2.5 Iterator iterate=currptr.children.iterator(); 180 bdemsky 1.1.2.5 while (iterate.hasNext()) { 181 bdemsky 1.1.2.5 todo.push(iterate.next()); 182 bdemsky 1.1.2.5 } 183 bdemsky 1.1.2.5 iterate=currptr.entries.iterator(); 184 bdemsky 1.1.2.5 while (iterate.hasNext()) 185 bdemsky 1.1.2.5 A.remove(iterate.next()); 186 bdemsky 1.1.2.5 } 187 bdemsky 1.1.2.5 return A; 188 bdemsky 1.1.2.1 } 189 bdemsky 1.1.2.5 190 bdemsky 1.1.2.3 /** Returns a <code>Set</code> of loops that are nested inside of this loop.*/ 191 bdemsky 1.1.2.5 192 bdemsky 1.1.2.4 public Set nestedLoops() { 193 bdemsky 1.1.2.5 analyze(); 194 bdemsky 1.1.2.5 WorkSet L=new WorkSet(); 195 bdemsky 1.1.2.5 Iterator iterate=ptr.children.iterator(); 196 bdemsky 1.1.2.5 while (iterate.hasNext()) 197 cananian 1.1.2.11 L.push(new LoopFinder(hc,grapher,dominator,root,(Loop) iterate.next())); 198 bdemsky 1.1.2.5 return L; 199 bdemsky 1.1.2.1 } 200 bdemsky 1.1.2.5 201 bdemsky 1.1.2.3 /** Returns the <code>Loops</code> that contains this loop. 202 bdemsky 1.1.2.2 * If this is the top level loop, this call returns a null pointer.*/ 203 bdemsky 1.1.2.5 204 bdemsky 1.1.2.4 public Loops parentLoop() { 205 bdemsky 1.1.2.5 analyze(); 206 bdemsky 1.1.2.5 if (ptr.parent!=null) 207 cananian 1.1.2.11 return new LoopFinder(hc,grapher,dominator,root,ptr.parent); 208 bdemsky 1.1.2.5 else return null; 209 bdemsky 1.1.2.1 } 210 bdemsky 1.1.2.5 211 bdemsky 1.1.2.1 /*---------------------------*/ 212 bdemsky 1.1.2.1 // public information accessor methods. 213 bdemsky 1.1.2.5 214 bdemsky 1.1.2.1 /*---------------------------*/ 215 bdemsky 1.1.2.1 // Analysis code. 216 bdemsky 1.1.2.5 217 bdemsky 1.1.2.5 218 bdemsky 1.1.2.1 /** Main analysis method. */ 219 bdemsky 1.1.2.5 220 bdemsky 1.1.2.1 void analyze() { 221 bdemsky 1.1.2.5 //Have we analyzed this set before? 222 bdemsky 1.1.2.5 //If so, don't do it again!!! 223 bdemsky 1.1.2.5 if (hc!=lasthc) { 224 bdemsky 1.1.2.5 225 bdemsky 1.1.2.5 //Did the caller hand us a bogus object? 226 bdemsky 1.1.2.5 //If so, throw it something 227 bdemsky 1.1.2.5 228 bdemsky 1.1.2.5 lasthc=hc; 229 bdemsky 1.1.2.5 230 bdemsky 1.1.2.5 //Set up the top level loop, so we can fill it with HCodeElements 231 bdemsky 1.1.2.5 //as we go along 232 bdemsky 1.1.2.5 root=new Loop(); 233 bdemsky 1.1.2.5 root.header=hc.getRootElement(); 234 bdemsky 1.1.2.5 235 bdemsky 1.1.2.5 //Set up a WorkSet for storing loops before we build the 236 bdemsky 1.1.2.5 //nested loop tree 237 bdemsky 1.1.2.5 setofloops=new WorkSet(); 238 bdemsky 1.1.2.5 239 bdemsky 1.1.2.5 //Find loops 240 bdemsky 1.1.2.5 findloopheaders(hc.getRootElement()); 241 bdemsky 1.1.2.5 242 bdemsky 1.1.2.5 //Build the nested loop tree 243 bdemsky 1.1.2.5 buildtree(); 244 bdemsky 1.1.2.5 } 245 bdemsky 1.1.2.1 } 246 bdemsky 1.1.2.1 // end analysis. 247 bdemsky 1.1.2.5 248 bdemsky 1.1.2.1 void buildtree() { 249 bdemsky 1.1.2.5 //go through set of generated loops 250 bdemsky 1.1.2.5 while(!setofloops.isEmpty()) { 251 bdemsky 1.1.2.5 252 bdemsky 1.1.2.5 //Pull out one 253 cananian 1.4 Loop A=(Loop) setofloops.removeLast(); 254 bdemsky 1.1.2.5 255 bdemsky 1.1.2.5 //Add it to the tree, complain if oddness 256 bdemsky 1.1.2.5 if (addnode(A, root)!=1) 257 bdemsky 1.1.2.5 System.out.println("Evil Error in LoopFinder while building tree."); 258 bdemsky 1.1.2.5 } 259 bdemsky 1.1.2.1 } 260 bdemsky 1.1.2.1 261 bdemsky 1.1.2.2 //Adds a node to the tree...Its recursive 262 bdemsky 1.1.2.5 263 bdemsky 1.1.2.1 int addnode(Loop A, Loop treenode) { 264 bdemsky 1.1.2.2 265 bdemsky 1.1.2.5 //Only need to go deeper if the header is contained in this loop 266 bdemsky 1.1.2.5 if (treenode.entries.contains(A.header)) 267 bdemsky 1.1.2.5 268 bdemsky 1.1.2.5 //Do we share headers? 269 bdemsky 1.1.2.5 if (treenode.header!=A.header) { 270 bdemsky 1.1.2.5 271 bdemsky 1.1.2.5 //No... Loop through our children to see if they want this 272 bdemsky 1.1.2.5 //node. 273 bdemsky 1.1.2.5 274 bdemsky 1.1.2.5 //Use integers for tri-state: 275 bdemsky 1.1.2.5 //0=not stored here, 1=stored and everything is good 276 bdemsky 1.1.2.5 //2=combined 2 natural loops with same header...need cleanup 277 bdemsky 1.1.2.5 278 bdemsky 1.1.2.5 int stored=0; 279 bdemsky 1.1.2.5 Iterator iterate=treenode.children.iterator(); 280 bdemsky 1.1.2.5 Loop temp=new Loop(); 281 bdemsky 1.1.2.5 while (iterate.hasNext()) { 282 bdemsky 1.1.2.5 temp=(Loop) iterate.next(); 283 bdemsky 1.1.2.5 stored=addnode(A,temp); 284 bdemsky 1.1.2.5 if (stored!=0) break; 285 bdemsky 1.1.2.5 } 286 bdemsky 1.1.2.5 287 bdemsky 1.1.2.5 //See what our children did for us 288 bdemsky 1.1.2.5 289 bdemsky 1.1.2.5 if (stored==0) { 290 bdemsky 1.1.2.5 //We get a new child... 291 bdemsky 1.1.2.5 treenode.children.push(A); 292 bdemsky 1.1.2.5 temp=A; 293 bdemsky 1.1.2.5 } 294 bdemsky 1.1.2.5 295 bdemsky 1.1.2.5 //Need to do cleanup for case 0 or 2 296 bdemsky 1.1.2.5 //temp points to the new child 297 bdemsky 1.1.2.5 298 bdemsky 1.1.2.5 if (stored!=1) { 299 bdemsky 1.1.2.5 300 bdemsky 1.1.2.5 //Have to make sure that none of the nodes under this one 301 bdemsky 1.1.2.5 //are children of the new node 302 bdemsky 1.1.2.5 303 bdemsky 1.1.2.5 Iterator iterate2=treenode.children.iterator(); 304 bdemsky 1.1.2.5 temp.parent=treenode; 305 bdemsky 1.1.2.5 306 bdemsky 1.1.2.5 //Loop through the children 307 bdemsky 1.1.2.5 while (iterate2.hasNext()) { 308 bdemsky 1.1.2.5 Loop temp2=(Loop)iterate2.next(); 309 bdemsky 1.1.2.5 310 bdemsky 1.1.2.5 //Don't look at the new node...otherwise we will create 311 bdemsky 1.1.2.5 //a unreachable subtree 312 bdemsky 1.1.2.5 313 bdemsky 1.1.2.5 if (temp2!=temp) 314 bdemsky 1.1.2.5 //If the new node has a childs header 315 bdemsky 1.1.2.5 //give the child up to it... 316 bdemsky 1.1.2.5 317 bdemsky 1.1.2.5 if (temp.entries.contains(temp2.header)) { 318 bdemsky 1.1.2.5 temp.children.push(temp2); 319 bdemsky 1.1.2.5 iterate2.remove(); 320 bdemsky 1.1.2.5 } 321 bdemsky 1.1.2.5 } 322 bdemsky 1.1.2.5 } 323 bdemsky 1.1.2.5 324 bdemsky 1.1.2.5 //We fixed everything...let our parents know 325 bdemsky 1.1.2.5 return 1; 326 bdemsky 1.1.2.5 } else { 327 bdemsky 1.1.2.5 //need to combine loops 328 bdemsky 1.1.2.5 while (!A.entries.isEmpty()) { 329 cananian 1.4 treenode.entries.push(A.entries.removeLast()); 330 bdemsky 1.1.2.5 } 331 bdemsky 1.1.2.5 //let the previous caller know that they have stuff todo 332 bdemsky 1.1.2.5 return 2; 333 bdemsky 1.1.2.5 } 334 bdemsky 1.1.2.5 //We aren't adopting the new node 335 bdemsky 1.1.2.5 else return 0; 336 bdemsky 1.1.2.1 } 337 bdemsky 1.1.2.1 338 pnkfelix 1.1.2.13 void findloopheaders(HCodeElement current_nodeOrig) { 339 pnkfelix 1.1.2.13 Stack stk = new Stack(); 340 pnkfelix 1.1.2.13 stk.push( current_nodeOrig ); 341 pnkfelix 1.1.2.13 while( ! stk.isEmpty() ){ 342 pnkfelix 1.1.2.13 HCodeElement current_node = (HCodeElement) stk.pop(); 343 pnkfelix 1.1.2.13 //look at the current node 344 pnkfelix 1.1.2.13 visit(current_node); 345 pnkfelix 1.1.2.13 346 pnkfelix 1.1.2.13 //add it to the all inclusive root loop 347 pnkfelix 1.1.2.13 root.entries.push(current_node); 348 pnkfelix 1.1.2.13 349 pnkfelix 1.1.2.13 //See if those we dominate are backedges 350 pnkfelix 1.1.2.13 HCodeElement[] children=dominator.children(current_node); 351 pnkfelix 1.1.2.13 for (int i=0;i<children.length;i++) 352 pnkfelix 1.1.2.13 stk.push( children[i] ); 353 pnkfelix 1.1.2.13 } 354 bdemsky 1.1.2.1 } 355 bdemsky 1.1.2.1 356 bdemsky 1.1.2.5 void visit(HCodeElement q) { 357 bdemsky 1.1.2.5 Loop A=new Loop(); 358 bdemsky 1.1.2.5 WorkSet B=new WorkSet(); 359 bdemsky 1.1.2.5 360 bdemsky 1.1.2.5 //Loop through all of our outgoing edges 361 cananian 1.5 for (Object succ_qO : grapher.succC(q)) { 362 cananian 1.5 HCodeEdge succ_q = (HCodeEdge) succ_qO; 363 bdemsky 1.1.2.5 HCodeElement temp=q; 364 bdemsky 1.1.2.5 365 bdemsky 1.1.2.5 //Go up the dominator tree until 366 bdemsky 1.1.2.5 //we hit the root element or we 367 bdemsky 1.1.2.5 //find the node we jump back too 368 bdemsky 1.1.2.5 while ((temp!=(hc.getRootElement()))&& 369 cananian 1.3 (succ_q.to()!=temp)) { 370 cananian 1.1.2.9 temp=dominator.idom(temp); 371 bdemsky 1.1.2.5 } 372 bdemsky 1.1.2.5 373 bdemsky 1.1.2.5 //If we found the node we jumped back to 374 bdemsky 1.1.2.5 //then build loop 375 bdemsky 1.1.2.5 376 cananian 1.3 if (succ_q.to()==temp) { 377 bdemsky 1.1.2.5 378 bdemsky 1.1.2.5 //found a loop 379 bdemsky 1.1.2.5 A.entries.push(temp); //Push the header 380 bdemsky 1.1.2.5 A.header=temp; 381 bdemsky 1.1.2.5 B.push(q); //Put the backedge in the todo list 382 bdemsky 1.1.2.5 383 bdemsky 1.1.2.5 //Starting with the backedge, work on the incoming edges 384 bdemsky 1.1.2.5 //until we get back to the loop header... 385 bdemsky 1.1.2.5 //Then we have the entire natural loop 386 bdemsky 1.1.2.5 387 bdemsky 1.1.2.5 while(!B.isEmpty()) { 388 cananian 1.4 HCodeElement newnode=(HCodeElement)B.removeLast(); 389 bdemsky 1.1.2.5 390 bdemsky 1.1.2.5 //Add all of the new incoming edges that we haven't already 391 bdemsky 1.1.2.5 //visited 392 cananian 1.5 for (Object pred_newnodeO : grapher.predC(newnode)) { 393 cananian 1.5 HCodeEdge pred_newnode = (HCodeEdge) pred_newnodeO; 394 cananian 1.3 if (!A.entries.contains(pred_newnode.from())) 395 cananian 1.3 B.push(pred_newnode.from()); 396 bdemsky 1.1.2.5 } 397 bdemsky 1.1.2.5 398 bdemsky 1.1.2.5 //push the new node on our list of nodes in the loop 399 bdemsky 1.1.2.5 A.entries.push(newnode); 400 bdemsky 1.1.2.5 } 401 bdemsky 1.1.2.2 402 bdemsky 1.1.2.5 //save our new loop 403 bdemsky 1.1.2.5 setofloops.push(A); 404 bdemsky 1.1.2.1 } 405 bdemsky 1.1.2.5 } 406 bdemsky 1.1.2.5 } 407 bdemsky 1.1.2.1 408 bdemsky 1.1.2.5 //Structure for building internal trees... 409 bdemsky 1.1.2.5 410 bdemsky 1.1.2.5 class Loop { 411 bdemsky 1.1.2.5 public WorkSet entries=new WorkSet(); 412 bdemsky 1.1.2.1 public HCodeElement header; 413 bdemsky 1.1.2.5 //Elements of the WorkSet of children are 414 bdemsky 1.1.2.5 //of the type Loop 415 bdemsky 1.1.2.5 public WorkSet children=new WorkSet(); 416 bdemsky 1.1.2.5 public Loop parent; 417 bdemsky 1.1.2.5 } 418 cananian 1.2 }