/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.compilers.opt.util; import java.util.Enumeration; /** * An efficient topsort dataflow iterator to be used with * SortedGraphNode. The graph represents entities (values, * statements, block, etc) to analyze and the graph makes explicit the * data-flow dependencies between them. Fixed-point iteration is * expressed using a special iterator that takes a parameter denoting * whether analysis of the current element changed the data-flow * result. If not, the iterator continues thru other unanalyzed * elements. If there is a change, then the data-flow successors of * the current node become the new head of the order of remaining * nodes. * * A typical use is as follows: * BasicBlock start = ir.cfg.entry(); * SortedGraphIterator bbIter = new SortedGraphIterator(start, true); * // true means forward analysis; false means backward analysis * for (BasicBlock currBlock = start; currBlock!= null;) { * * // do your analysis of the currBlock here * * boolean changed = ... // true if the solution of currBlock has been changed since * // the last visit of currBlock. * // false if not. * * currBlock = (BasicBlock) bbIter.markAndGetNextTopSort(changed); * } */ public class SortedGraphIterator { /** * The earliest place where we needed to move currentNode back in the list * because its successor needed to be processed. */ protected SortedGraphNode barrier; /** * A unique marker to use to mark nodes */ protected int changeMark; /** * The current node we are processing */ protected SortedGraphNode currentNode; /** * The direction we are moving on the graph */ protected boolean forward; /** * Cosntructor * @param current the node to start the iteration at * @param forward the direction we are processing the graph */ public SortedGraphIterator(SortedGraphNode current, boolean forward) { currentNode = current; barrier = current.getSortedNext(forward); this.forward = forward; changeMark = SortedGraphNode.getNewSortMarker(current); currentNode.setSortMarker(Integer.MIN_VALUE); } /** * General fixed-pointer iterator; call this repeatedly until there * is no more work to do. There are specialized (more efficient) * mechanisms provided by this class. * * @param changed Whether analysis of the current element changed * any data-flow result. * * @return the next node to analyze * * @see #isSingleSuccessor * @see #isSinglePredecessor */ public SortedGraphNode markAndGetNextTopSort(boolean changed) { if (changed) { int currOrder = currentNode.getSortNumber(forward); int newOrder = currOrder + 1; // currentNode can be a target to be re-executed int barrierOrder; if (barrier == null) { barrierOrder = Integer.MAX_VALUE; } else { barrierOrder = barrier.getSortNumber(forward); } SortedGraphNode newNode = null; Enumeration<? extends SortedGraphNode> e; if (forward) { e = currentNode.getOutNodes(); } else { e = currentNode.getInNodes(); } while (e.hasMoreElements()) { // Select the node with the smallest sort number among the "successor" nodes SortedGraphNode outNode = e.nextElement(); if (outNode.getSortNumber(forward) < barrierOrder) { // anything larger than barrier will be visited later outNode.setSortMarker(changeMark); if (outNode.getSortNumber(forward) < newOrder) { // have to go backward newOrder = outNode.getSortNumber(forward); newNode = outNode; } } } if (newOrder <= currOrder) { currentNode = newNode; // retreat advanceBarrier(); return newNode; } } // Either changed = false or no retreat // Return the first one with changeMark before barrier or // barrier itself. currentNode = currentNode.getSortedNext(forward); for (; currentNode != barrier; currentNode = currentNode.getSortedNext(forward)) { if (currentNode.getSortMarker() == changeMark) { advanceBarrier(); return currentNode; } } // Nothing before the barrier advanceBarrier(); return currentNode; } /** * This method checks to see if the second parameter has a single * predecessor, which is the first parameter. * If this condition is true, data flow analyses can reuse their * results from the previous iteration rather than perform a meet operation * (See LiveAnalysis.java for an example.) * * @param currentNode the possibly unique predecessor * @param nextNode the node of interest * @return if first parameter is the only predecessor of the 2nd parameter */ public boolean isSingleSuccessor(SortedGraphNode currentNode, SortedGraphNode nextNode) { // check that next node has only 1 predecessor if (!nextNode.hasOneIn()) return false; // now check that the predecessor is current node Enumeration<? extends SortedGraphNode> inEnum = nextNode.getInNodes(); return inEnum.nextElement() == currentNode; } /** * This method checks to see if the second parameter has a single * successor, which is the first parameter. * If this condition is true, data flow analyses can reuse their * results from the previous iteration rather than perform a meet operation * (See LiveAnalysis.java for an example.) * * @param currentNode the possibly unique predecessor * @param nextNode the node of interest * @return if first parameter is the only succesor of the 2nd parameter */ public boolean isSinglePredecessor(SortedGraphNode currentNode, SortedGraphNode nextNode) { // check that next node has only 1 successor if (!nextNode.hasOneOut()) return false; // now check that the successor is current node Enumeration<? extends SortedGraphNode> outEnum = nextNode.getOutNodes(); return outEnum.nextElement() == currentNode; } /** * This method keeps track of nodes in the graph that are known to * not have been visited yet even once. Advance the barrier, if needed */ private void advanceBarrier() { if (currentNode != null) { currentNode.setSortMarker(Integer.MIN_VALUE); } if ((currentNode == barrier) && (barrier != null)) { barrier = barrier.getSortedNext(forward); } } }