/*
* 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.controlflow;
import java.util.Enumeration;
import org.jikesrvm.compilers.opt.ir.BasicBlock;
import org.jikesrvm.compilers.opt.ir.IR;
import org.jikesrvm.compilers.opt.util.TreeNode;
import org.jikesrvm.util.BitVector;
/**
* This class implements a node in the dominator tree.
*
* <p> TODO: we do not support IRs with exception handlers!!
*/
public class DominatorTreeNode extends TreeNode {
/**
* the basic block this node represents
*/
private final BasicBlock block;
/**
* distance from the root of the dominator tree, lazily initialized (-1 => not
* initialized)
*/
private int depth = -1;
/**
* representation of the dominance frontier for this node
*/
private BitVector dominanceFrontier;
/**
* the cache to hold the set of nodes that dominate this one. This is
* computed on demand by walking up the tree.
*/
BitVector dominators;
/**
* lower bound of dominated nodes range
*/
private int low = 0;
/**
* upper bound of dominated nodes range
*/
private int high = 0;
/**
* Construct a dominator tree node for a given basic block.
* @param block the basic block
*/
DominatorTreeNode(BasicBlock block) {
this.block = block;
}
/**
* Get the basic block for this dominator tree node
* @return the basic block
*/
public BasicBlock getBlock() {
return block;
}
/**
* Return the distance of this node from the root of the dominator tree.
* @return the distance of this node from the root of the dominator tree.
*/
int getDepth() {
if (depth == -1) {
DominatorTreeNode dad = (DominatorTreeNode) getParent();
if (dad == null) {
depth = 0;
} else {
depth = dad.getDepth() + 1;
}
}
return depth;
}
/**
* Return a bit set representing the dominance frontier for this node
* @return a bit set representing the dominance frontier for this node
*/
BitVector getDominanceFrontier() {
return dominanceFrontier;
}
/**
* Set a bit set representing the dominance frontier for this node
* @param set the bit set
*/
void setDominanceFrontier(BitVector set) {
dominanceFrontier = set;
}
/**
* Return a string representation of the dominance frontier for this
* node.
* @return a string representation of the dominance frontier for this
* node
*/
String dominanceFrontierString() {
return dominanceFrontier.toString();
}
/**
* This method returns the set of blocks that dominates the passed
* block, i.e., it answers the question "Who dominates me?"
*
* @param ir the governing IR
* @return a BitVector containing those blocks that dominate me
*/
BitVector dominators(IR ir) {
// Currently, this set is computed on demand,
// but we cache it for the next time.
if (dominators == null) {
dominators = new BitVector(ir.getMaxBasicBlockNumber() + 1);
dominators.set(block.getNumber());
DominatorTreeNode node = this;
while ((node = (DominatorTreeNode) getParent()) != null) {
dominators.set(node.getBlock().getNumber());
}
}
return dominators;
}
/**
* This method returns true if the passed node dominates this node
* @param master the proposed dominating node
* @return whether the passed node dominates me
*/
boolean _isDominatedBy(DominatorTreeNode master) {
DominatorTreeNode node = this;
while ((node != null) && (node != master)) {
node = (DominatorTreeNode) node.getParent();
}
return node == master;
}
/**
* This method returns true if the passed node dominates this node
* @param master the proposed dominating node
* @return whether the passed node dominates me
*/
boolean isDominatedBy(DominatorTreeNode master) {
if (low == 0) initializeRanges();
return master.low <= low && master.high >= high;
}
private void initializeRanges() {
DominatorTreeNode node = this;
DominatorTreeNode parent = (DominatorTreeNode) getParent();
while (parent != null) {
node = parent;
parent = (DominatorTreeNode) node.getParent();
}
node.initializeRanges(0);
}
private int initializeRanges(int i) {
low = ++i;
Enumeration<TreeNode> childEnum = getChildren();
while (childEnum.hasMoreElements()) {
DominatorTreeNode child = (DominatorTreeNode) childEnum.nextElement();
i = child.initializeRanges(i);
}
high = ++i;
return i;
}
/**
* Enumerate the basic blocks in the dominance frontier for this node.
* @param ir the governing IR
* @return an enumeration of the basic blocks in the dominance frontier
* for this node.
*/
Enumeration<BasicBlock> domFrontierEnumerator(IR ir) {
return ir.getBasicBlocks(dominanceFrontier);
}
/**
* String-i-fies the node
* @return the node as a string
*/
@Override
public final String toString() {
StringBuilder sb = new StringBuilder();
sb.append(block);
sb.append(" (").append(low).append(", ").append(high).append(")");
return sb.toString();
}
}