001/* 002 * This file is part of the Jikes RVM project (http://jikesrvm.org). 003 * 004 * This file is licensed to You under the Eclipse Public License (EPL); 005 * You may not use this file except in compliance with the License. You 006 * may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/eclipse-1.0.php 009 * 010 * See the COPYRIGHT.txt file distributed with this work for information 011 * regarding copyright ownership. 012 */ 013package org.jikesrvm.compilers.opt.util; 014 015import java.util.Enumeration; 016 017 018/** 019 * An efficient topsort dataflow iterator to be used with 020 * SortedGraphNode. The graph represents entities (values, 021 * statements, block, etc) to analyze and the graph makes explicit the 022 * data-flow dependencies between them. Fixed-point iteration is 023 * expressed using a special iterator that takes a parameter denoting 024 * whether analysis of the current element changed the data-flow 025 * result. If not, the iterator continues thru other unanalyzed 026 * elements. If there is a change, then the data-flow successors of 027 * the current node become the new head of the order of remaining 028 * nodes. 029 * <p> 030 * A typical use is as follows: 031 * <pre> 032 * BasicBlock start = ir.cfg.entry(); 033 * SortedGraphIterator bbIter = new SortedGraphIterator(start, true); 034 * // true means forward analysis; false means backward analysis 035 * for (BasicBlock currBlock = start; currBlock!= null;) { 036 * 037 * // do your analysis of the currBlock here 038 * 039 * boolean changed = ... // true if the solution of currBlock has been changed since 040 * // the last visit of currBlock. 041 * // false if not. 042 * 043 * currBlock = (BasicBlock) bbIter.markAndGetNextTopSort(changed); 044 * } 045 *</pre> 046 */ 047public class SortedGraphIterator { 048 049 /** 050 * The earliest place where we needed to move currentNode back in the list 051 * because its successor needed to be processed. 052 */ 053 protected SortedGraphNode barrier; 054 055 /** 056 * A unique marker to use to mark nodes 057 */ 058 protected int changeMark; 059 060 /** 061 * The current node we are processing 062 */ 063 protected SortedGraphNode currentNode; 064 065 /** 066 * The direction we are moving on the graph 067 */ 068 protected boolean forward; 069 070 /** 071 * Constructor 072 * @param current the node to start the iteration at 073 * @param forward the direction we are processing the graph 074 */ 075 public SortedGraphIterator(SortedGraphNode current, boolean forward) { 076 currentNode = current; 077 barrier = current.getSortedNext(forward); 078 this.forward = forward; 079 changeMark = SortedGraphNode.getNewSortMarker(current); 080 currentNode.setSortMarker(Integer.MIN_VALUE); 081 } 082 083 /** 084 * General fixed-pointer iterator; call this repeatedly until there 085 * is no more work to do. There are specialized (more efficient) 086 * mechanisms provided by this class. 087 * 088 * @param changed Whether analysis of the current element changed 089 * any data-flow result. 090 * 091 * @return the next node to analyze 092 * 093 * @see #isSingleSuccessor 094 * @see #isSinglePredecessor 095 */ 096 public SortedGraphNode markAndGetNextTopSort(boolean changed) { 097 if (changed) { 098 int currOrder = currentNode.getSortNumber(forward); 099 int newOrder = currOrder + 1; // currentNode can be a target to be re-executed 100 int barrierOrder; 101 if (barrier == null) { 102 barrierOrder = Integer.MAX_VALUE; 103 } else { 104 barrierOrder = barrier.getSortNumber(forward); 105 } 106 SortedGraphNode newNode = null; 107 Enumeration<? extends SortedGraphNode> e; 108 if (forward) { 109 e = currentNode.getOutNodes(); 110 } else { 111 e = currentNode.getInNodes(); 112 } 113 114 while (e.hasMoreElements()) { 115 // Select the node with the smallest sort number among the "successor" nodes 116 SortedGraphNode outNode = e.nextElement(); 117 if (outNode.getSortNumber(forward) < barrierOrder) { // anything larger than barrier will be visited later 118 outNode.setSortMarker(changeMark); 119 if (outNode.getSortNumber(forward) < newOrder) { // have to go backward 120 newOrder = outNode.getSortNumber(forward); 121 newNode = outNode; 122 } 123 } 124 } 125 if (newOrder <= currOrder) { 126 currentNode = newNode; 127 // retreat 128 advanceBarrier(); 129 return newNode; 130 } 131 } 132 133 // Either changed = false or no retreat 134 // Return the first one with changeMark before barrier or 135 // barrier itself. 136 currentNode = currentNode.getSortedNext(forward); 137 for (; currentNode != barrier; currentNode = currentNode.getSortedNext(forward)) { 138 if (currentNode.getSortMarker() == changeMark) { 139 advanceBarrier(); 140 return currentNode; 141 } 142 } 143 144 // Nothing before the barrier 145 advanceBarrier(); 146 return currentNode; 147 } 148 149 /** 150 * This method checks to see if the second parameter has a single 151 * predecessor, which is the first parameter. 152 * If this condition is true, data flow analyses can reuse their 153 * results from the previous iteration rather than perform a meet operation 154 * (See LiveAnalysis.java for an example.) 155 * 156 * @param currentNode the possibly unique predecessor 157 * @param nextNode the node of interest 158 * @return if first parameter is the only predecessor of the 2nd parameter 159 */ 160 public boolean isSingleSuccessor(SortedGraphNode currentNode, SortedGraphNode nextNode) { 161 // check that next node has only 1 predecessor 162 if (!nextNode.hasOneIn()) return false; 163 // now check that the predecessor is current node 164 Enumeration<? extends SortedGraphNode> inEnum = nextNode.getInNodes(); 165 return inEnum.nextElement() == currentNode; 166 } 167 168 /** 169 * This method checks to see if the second parameter has a single 170 * successor, which is the first parameter. 171 * If this condition is true, data flow analyses can reuse their 172 * results from the previous iteration rather than perform a meet operation 173 * (See LiveAnalysis.java for an example.) 174 * 175 * @param currentNode the possibly unique predecessor 176 * @param nextNode the node of interest 177 * @return if first parameter is the only successor of the 2nd parameter 178 */ 179 public boolean isSinglePredecessor(SortedGraphNode currentNode, SortedGraphNode nextNode) { 180 // check that next node has only 1 successor 181 if (!nextNode.hasOneOut()) return false; 182 // now check that the successor is current node 183 Enumeration<? extends SortedGraphNode> outEnum = nextNode.getOutNodes(); 184 return outEnum.nextElement() == currentNode; 185 } 186 187 /** 188 * This method keeps track of nodes in the graph that are known to 189 * not have been visited yet even once. Advance the barrier, if needed 190 */ 191 private void advanceBarrier() { 192 if (currentNode != null) { 193 currentNode.setSortMarker(Integer.MIN_VALUE); 194 } 195 if ((currentNode == barrier) && (barrier != null)) { 196 barrier = barrier.getSortedNext(forward); 197 } 198 } 199} 200