/*
* 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;
/**
* Depth First Spanning Tree, builds topological sort of a graph consisting of SortedGraphNode.
*/
public final class TopSort extends Stack<SortedGraphNode> {
/**
* the "visited" marker to use
*/
private int sortMarker;
/**
* the next "number" to give out
*/
private int sortNumber;
/**
* the last node to get a number
*/
private SortedGraphNode lastNumberedNode;
/**
* are we processing the graph in forward order?
*/
private boolean forward;
/**
* Prevent instantiation
*/
private TopSort() { }
/**
* @param graph the graph
* @param forward should we treat edges as forward?
* This is the second version of the implementation
* (see CVS file for older one)
* @return the last sorted node
*/
public static SortedGraphNode buildTopological(TopSortInterface graph, boolean forward) {
SortedGraphNode start = graph.startNode(forward);
TopSort sorter = new TopSort();
sorter.sortMarker = SortedGraphNode.getNewSortMarker(start);
sorter.forward = forward;
sorter.DFS(start, graph.numberOfNodes());
return sorter.lastNumberedNode;
}
/**
* Depth-first numbering in a non-recursive manner
* @param node the root node
* @param numNodes the number of nodes in this graph
*/
private void DFS(SortedGraphNode node, int numNodes) {
// push node on to the emulated activation stack
push(node);
@SuppressWarnings("unchecked") // the java generic array problem
Enumeration<? extends SortedGraphNode>[] nodeEnum = new Enumeration[numNodes];
recurse:
while (!empty()) {
node = peek();
// check if we were already processing this node, if so we would have
// saved the state of the enumeration in the loop below
Enumeration<? extends SortedGraphNode> _enum = nodeEnum[node.getNumber()];
if (_enum == null) {
// mark node as visited
node.setSortMarker(sortMarker);
if (forward) {
_enum = node.getOutNodes();
} else {
_enum = node.getInNodes();
}
}
while (_enum.hasMoreElements()) {
SortedGraphNode target = _enum.nextElement();
// have we visited target?
if (target.getSortMarker() != sortMarker) {
// simulate a recursive call
// but first save the enumeration state for resumption later
nodeEnum[node.getNumber()] = _enum;
push(target);
continue recurse;
}
}
// give node the next smallest number
node.setSortNumber(sortNumber--, forward);
// link it to the previous smallest node, even if that node is null
node.setSortedNext(lastNumberedNode, forward);
// update the smallest node
lastNumberedNode = node;
// "Pop" from the emulated activiation stack
pop();
}
}
}