Mirror of the BLOAT repository https://www.cs.purdue.edu/homes/hosking/bloat/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
bloat/src/EDU/purdue/cs/bloat/cfg/Block.java

371 lines
9.0 KiB

/**
* All files in the distribution of BLOAT (Bytecode Level Optimization and
* Analysis tool for Java(tm)) are Copyright 1997-2001 by the Purdue
* Research Foundation of Purdue University. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package EDU.purdue.cs.bloat.cfg;
import java.util.*;
import EDU.purdue.cs.bloat.editor.*;
import EDU.purdue.cs.bloat.tree.*;
import EDU.purdue.cs.bloat.util.*;
/**
* <tt>Block</tt> represents a basic block of code used in control flow
* graphs. A basic block is always entered at its beginning and exits at its
* end. That is, its first statement is a label and its last statement is a
* jump. There are no other labels or jumps in between.
* <p>
* Each <tt>Block</tt> knows its parent block and its children in the
* dominator and postdominator trees. It also knows which blocks are in its
* dominance frontier and its postdominance frontier.
*
* @see FlowGraph
* @see DominatorTree
* @see DominanceFrontier
*/
public class Block extends GraphNode {
// There are several "types" of Blocks. A NON_HEADER block is not the
// header of a loop. An IRREDUCIBLE block is one of the headers of an
// irreducible loop. An irriducible loop has more than one entry
// point. They are very rare and are really ugly. The loop
// transformer tries to fix up mutiple headers. A REDUCIBLE header is
// a header for a reducible loop.
public static final int NON_HEADER = 0;
public static final int IRREDUCIBLE = 1;
public static final int REDUCIBLE = 2;
FlowGraph graph; // CFG to which this Block belongs
Label label; // This Block's Label
Tree tree; // Expression tree for this block
Block domParent; // Block that (immediately) dominates this Block
Block pdomParent;
Set domChildren; // Blocks that this Block dominates
Set pdomChildren; // The postdominator children of this block
Set domFrontier; // This Block's dominance frontier
Set pdomFrontier; // This Block's postdominace frontier
int blockType; // NON_HEADER, IRREDUCIBLE, or REDUCIBLE
Block header; // The block's loop header
StackOptimizer stackOptimizer; // Stack Optimizer
/**
* Constructor.
*
* @param label
* The block's label. The label may be thought of as the line of
* code at which the block begins.
* @param graph
* The CFG containing the block.
*/
Block(final Label label, final FlowGraph graph) {
this.label = label;
this.graph = graph;
this.tree = null;
this.header = null;
this.blockType = Block.NON_HEADER;
label.setStartsBlock(true);
domParent = null;
pdomParent = null;
domChildren = new HashSet();
pdomChildren = new HashSet();
domFrontier = new HashSet();
pdomFrontier = new HashSet();
stackOptimizer = new StackOptimizer(this); // make StackOptimizer
// object
}
/**
* Returns the stack optimizer for this block.
*
* @return The stack optimizer.
*/
public StackOptimizer stackOptimizer() {
return stackOptimizer;
}
/**
* Returns the expression tree for this block.
*
* @return The tree.
*/
public Tree tree() {
return tree;
}
/**
* Sets the expression tree for this block.
*/
public void setTree(final Tree tree) {
this.tree = tree;
}
/**
* Returns the CFG containing the block.
*
* @return The CFG.
*/
public FlowGraph graph() {
return graph;
}
/**
* Returns the label associated with this block.
*/
public Label label() {
return label;
}
/**
* Visits the expression tree contained in this block.
*/
public void visitChildren(final TreeVisitor visitor) {
if (tree != null) {
tree.visit(visitor);
}
}
public void visit(final TreeVisitor visitor) {
visitor.visitBlock(this);
}
/**
* Sets the type of this Block. A Block may have one of three types:
*
* <ul>
* <li><tt>NON_HEADER</tt>: Not the header of any loop
* <li><tt>IRREDUCIBLE</tt>: Header of an irreducible loop
* <li><tt>REDUCIBLE</tt>: Header of a reducible loop
* </ul>
*
* A <i>loop</i> is a strongly connected component of a control flow graph.
* A loop's <i>header</i> is the block that dominates all other blocks in
* the loop. A loop is <i>reducible</i> if the only way to enter the loop
* is through the header.
*/
void setBlockType(final int blockType) {
this.blockType = blockType;
if (FlowGraph.DEBUG) {
System.out.println(" Set block type " + this);
}
}
/**
* Returns the type of this Block.
*/
int blockType() {
return blockType;
}
public void setHeader(final Block header) {
this.header = header;
if (FlowGraph.DEBUG) {
System.out.println(" Set header " + this);
}
}
public Block header() {
return header;
}
/**
* Returns a string representation of this block.
*/
public String toString() {
String s = "<block " + label + " hdr=";
if (header != null) {
s += header.label();
} else {
s += "null";
}
switch (blockType) {
case NON_HEADER:
break;
case IRREDUCIBLE:
s += " irred";
break;
case REDUCIBLE:
s += " red";
break;
}
if (this == graph.source()) {
return s + " source>";
} else if (this == graph.init()) {
return s + " init>";
} else if (this == graph.sink()) {
return s + " sink>";
} else {
return s + ">";
}
}
/**
* Returns the basic blocks that this Block immediately dominates. That is,
* it returns this Block's children in the dominator tree for the CFG.
*/
Collection domChildren() {
return domChildren;
}
/**
* Returns the immediate dominator of this Block. That is, it returns the
* Block's parent in the dominator tree, its immediate dominator.
*/
Block domParent() {
return domParent;
}
/**
* Specifies that Block dominates this Block (parent in the dominator tree,
* the immediate dominator).
*
* @param block
* Block that dominates this Block.
*/
void setDomParent(final Block block) {
// If this Block already had a dominator specified, remove
// it from its dominator's children.
if (domParent != null) {
domParent.domChildren.remove(this);
}
domParent = block;
// Add this Block to its new dominator's children.
if (domParent != null) {
domParent.domChildren.add(this);
}
}
/**
* Returns whether or this Block dominates another given Block. A node X
* dominates a node Y when every path from the first node in the CFG (Enter)
* to Y must pass through X.
*/
public boolean dominates(final Block block) {
Block p = block;
while (p != null) {
if (p == this) {
return true;
}
p = p.domParent();
}
return false;
}
/**
* Returns the children of this Block in the CFG's postdominator tree.
*/
Collection pdomChildren() {
return pdomChildren;
}
/**
* Returns the parent of this Block in the CFG's postdominator tree.
*/
Block pdomParent() {
return pdomParent;
}
/**
* Sets this Block's parent in the postdominator tree.
*/
void setPdomParent(final Block block) {
if (pdomParent != null) {
pdomParent.pdomChildren.remove(this);
}
pdomParent = block;
if (pdomParent != null) {
pdomParent.pdomChildren.add(this);
}
}
/**
* Determines whether or not this block postdominates a given block. A block
* X is said to postdominate a block Y when every path from Y to the last
* node in the CFG (Exit) passes through X. This relationship can be thought
* of as the reverse of dominance. That is, X dominates Y in the reverse
* CFG.
*
* @see DominatorTree
*/
public boolean postdominates(final Block block) {
Block p = block;
while (p != null) {
if (p == this) {
return true;
}
p = p.pdomParent();
}
return false;
}
/**
* Returns the blocks that are in this block's dominance frontier. The
* dominance frontier of a node X in a CFG is the set of all nodes Y such
* that X dominates a predacessor of Y, but does not strictly dominate Y.
* Nodes in the dominance frontier always have more than one parent (a
* join).
*
* @see DominanceFrontier
*/
Collection domFrontier() {
Assert.isTrue(domFrontier != null);
return domFrontier;
}
/**
* Returns the postdominance frontier for this node. A postdominace frontier
* is essentially the same as a dominace frontier, but the postdominance
* relationship is used instead of the dominance relationship.
*/
Collection pdomFrontier() {
Assert.isTrue(pdomFrontier != null);
return pdomFrontier;
}
}