edu.umd.cs.findbugs.ba.AbstractDominatorsAnalysis Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spotbugs Show documentation
Show all versions of spotbugs Show documentation
SpotBugs: Because it's easy!
/*
* Bytecode Analysis Framework
* Copyright (C) 2003,2004 University of Maryland
*
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
package edu.umd.cs.findbugs.ba;
import java.util.BitSet;
import java.util.Iterator;
import javax.annotation.CheckForNull;
import org.apache.bcel.generic.InstructionHandle;
/**
* A dataflow analysis to compute dominator relationships between basic blocks.
* Use the {@link #getResultFact} method to get the dominator set for a given
* basic block. The dominator sets are represented using the
* {@link java.util.BitSet} class, with the individual bits corresponding to the
* IDs of basic blocks.
*
* Subclasses extend this class to compute either dominators or postdominators.
*
*
* An EdgeChooser may be specified to select which edges to take into account.
* For example, exception edges could be ignored.
*
*
* @author David Hovemeyer
* @see DataflowAnalysis
* @see CFG
* @see BasicBlock
*/
public abstract class AbstractDominatorsAnalysis extends BasicAbstractDataflowAnalysis {
private final CFG cfg;
private final EdgeChooser edgeChooser;
/**
* Constructor.
*
* @param cfg
* the CFG to compute dominator relationships for
* @param ignoreExceptionEdges
* true if exception edges should be ignored
*/
public AbstractDominatorsAnalysis(CFG cfg, final boolean ignoreExceptionEdges) {
this(cfg, edge -> {
return !(ignoreExceptionEdges && edge.isExceptionEdge());
});
}
/**
* Constructor.
*
* @param cfg
* the CFG to compute dominator relationships for
* @param edgeChooser
* EdgeChooser to choose which Edges to consider significant
*/
public AbstractDominatorsAnalysis(CFG cfg, EdgeChooser edgeChooser) {
this.cfg = cfg;
this.edgeChooser = edgeChooser;
}
@Override
public BitSet createFact() {
return new BitSet();
}
@Override
public void copy(BitSet source, BitSet dest) {
dest.clear();
dest.or(source);
}
@Override
public void initEntryFact(BitSet result) {
// No blocks dominate the entry block
result.clear();
}
@Override
public boolean isTop(BitSet fact) {
// We represent TOP as a bitset with an illegal bit set
return fact.get(cfg.getNumBasicBlocks());
}
@Override
public void makeFactTop(BitSet fact) {
// We represent TOP as a bitset with an illegal bit set
fact.set(cfg.getNumBasicBlocks());
}
@Override
public boolean same(BitSet fact1, BitSet fact2) {
return fact1.equals(fact2);
}
@Override
public void transfer(BasicBlock basicBlock, @CheckForNull InstructionHandle end, BitSet start, BitSet result)
throws DataflowAnalysisException {
// Start with intersection of dominators of predecessors
copy(start, result);
if (!isTop(result)) {
// Every block dominates itself
result.set(basicBlock.getLabel());
}
}
@Override
public void meetInto(BitSet fact, Edge edge, BitSet result) throws DataflowAnalysisException {
if (!edgeChooser.choose(edge)) {
return;
}
if (isTop(fact)) {
return;
} else if (isTop(result)) {
copy(fact, result);
} else {
// Meet is intersection
result.and(fact);
}
}
/**
* Get a bitset containing the unique IDs of all blocks which dominate (or
* postdominate) the given block.
*
* @param block
* a BasicBlock
* @return BitSet of the unique IDs of all blocks that dominate (or
* postdominate) the BasicBlock
*/
public BitSet getAllDominatorsOf(BasicBlock block) {
return getResultFact(block);
}
/**
* Get a bitset containing the unique IDs of all blocks in CFG dominated (or
* postdominated, depending on how the analysis was done) by given block.
*
* @param dominator
* we want to get all blocks dominated (or postdominated) by this
* block
* @return BitSet of the ids of all blocks dominated by the given block
*/
public BitSet getAllDominatedBy(BasicBlock dominator) {
BitSet allDominated = new BitSet();
for (Iterator i = cfg.blockIterator(); i.hasNext();) {
BasicBlock block = i.next();
BitSet dominators = getResultFact(block);
if (dominators.get(dominator.getLabel())) {
allDominated.set(block.getLabel());
}
}
return allDominated;
}
}