use of soot.toolkits.graph.Block in project soot by Sable.
the class GroupIntPair method calculateStackHeight.
private void calculateStackHeight(Block aBlock) {
int blockHeight = blockToStackHeight.get(aBlock).intValue();
if (blockHeight > maxStackHeight) {
maxStackHeight = blockHeight;
}
for (Unit u : aBlock) {
Inst nInst = (Inst) u;
blockHeight -= nInst.getInMachineCount();
if (blockHeight < 0) {
throw new RuntimeException("Negative Stack height has been attained in :" + aBlock.getBody().getMethod().getSignature() + " \n" + "StackHeight: " + blockHeight + "\n" + "At instruction:" + nInst + "\n" + "Block:\n" + aBlock + "\n\nMethod: " + aBlock.getBody().getMethod().getName() + "\n" + aBlock.getBody().getMethod());
}
blockHeight += nInst.getOutMachineCount();
if (blockHeight > maxStackHeight) {
maxStackHeight = blockHeight;
}
// logger.debug(">>> " + nInst + " " + blockHeight);
}
for (Block b : aBlock.getSuccs()) {
Integer i = blockToStackHeight.get(b);
if (i != null) {
if (i.intValue() != blockHeight) {
throw new RuntimeException(aBlock.getBody().getMethod().getSignature() + ": incoherent stack height at block merge point " + b + aBlock + "\ncomputed blockHeight == " + blockHeight + " recorded blockHeight = " + i.intValue());
}
} else {
blockToStackHeight.put(b, new Integer(blockHeight));
calculateStackHeight(b);
}
}
}
use of soot.toolkits.graph.Block in project soot by Sable.
the class Region method getUnits.
public List<Unit> getUnits() {
if (this.m_units == null) {
this.m_units = new LinkedList<Unit>();
for (Iterator<Block> itr = this.m_blocks.iterator(); itr.hasNext(); ) {
Block b = itr.next();
for (Iterator<Unit> itr1 = b.iterator(); itr1.hasNext(); ) {
Unit u = itr1.next();
((LinkedList<Unit>) this.m_units).addLast(u);
}
}
}
return this.m_units;
}
use of soot.toolkits.graph.Block in project soot by Sable.
the class RegionAnalysis method CFGtoString.
public static String CFGtoString(DirectedGraph<Block> cfg, boolean blockDetail) {
String s = "";
s += "Headers: " + cfg.getHeads().size() + " " + cfg.getHeads();
for (Block node : cfg) {
s += "Node = " + node.toShortString() + "\n";
s += "Preds:\n";
for (Iterator<Block> predsIt = cfg.getPredsOf(node).iterator(); predsIt.hasNext(); ) {
s += " ";
s += predsIt.next().toShortString() + "\n";
}
s += "Succs:\n";
for (Iterator<Block> succsIt = cfg.getSuccsOf(node).iterator(); succsIt.hasNext(); ) {
s += " ";
s += succsIt.next().toShortString() + "\n";
}
}
if (blockDetail) {
s += "Blocks Detail:";
for (Iterator<Block> it = cfg.iterator(); it.hasNext(); ) {
Block node = it.next();
s += node + "\n";
}
}
return s;
}
use of soot.toolkits.graph.Block in project soot by Sable.
the class HashMutablePDG method constructPDG.
/**
* This is the heart of the PDG contruction. It is huge and definitely needs
* some refactorings, but since it's been evlovong to cover some boundary cases
* it has become hard to rafactor.
*
* It uses the list of weak regions, along with the dominator and post-dominator
* trees to construct the PDG nodes.
*/
protected void constructPDG() {
Hashtable<Block, Region> block2region = this.m_regionAnalysis.getBlock2RegionMap();
DominatorTree<Block> pdom = this.m_regionAnalysis.getPostDominatorTree();
DominatorTree<Block> dom = this.m_regionAnalysis.getDominatorTree();
List<Region> regions2process = new LinkedList<Region>();
Region topLevelRegion = this.m_regionAnalysis.getTopLevelRegion();
m_strongRegionStartID = m_weakRegions.size();
// This becomes the top-level region (or ENTRY region node)
PDGNode pdgnode = new PDGNode(topLevelRegion, PDGNode.Type.REGION);
this.addNode(pdgnode);
this.m_obj2pdgNode.put(topLevelRegion, pdgnode);
this.m_startNode = pdgnode;
topLevelRegion.setParent(null);
Set<Region> processedRegions = new HashSet<Region>();
regions2process.add(topLevelRegion);
// while there's a (weak) region to process
while (!regions2process.isEmpty()) {
Region r = regions2process.remove(0);
processedRegions.add(r);
// get the corresponding pdgnode
pdgnode = this.m_obj2pdgNode.get(r);
/*
* For all the CFG nodes in the region, create the corresponding PDG node and edges, and
* process them if they are in the dependence set of other regions, i.e. other regions
* depend on them.
*/
List<Block> blocks = r.getBlocks();
Hashtable<Region, List<Block>> toBeRemoved = new Hashtable<Region, List<Block>>();
PDGNode prevPDGNodeInRegion = null;
PDGNode curNodeInRegion = null;
for (Iterator<Block> itr = blocks.iterator(); itr.hasNext(); ) {
/*
* Add the PDG node corresponding to the CFG block node.
*/
Block a = itr.next();
PDGNode pdgNodeOfA = null;
if (!this.m_obj2pdgNode.containsKey(a)) {
pdgNodeOfA = new PDGNode(a, PDGNode.Type.CFGNODE);
this.addNode(pdgNodeOfA);
this.m_obj2pdgNode.put(a, pdgNodeOfA);
} else
pdgNodeOfA = this.m_obj2pdgNode.get(a);
this.addEdge(pdgnode, pdgNodeOfA, "dependency");
pdgnode.addDependent(pdgNodeOfA);
//
curNodeInRegion = pdgNodeOfA;
/*
* For each successor B of A, if B does not post-dominate A, add all the
* nodes on the path from B to the L in the post-dominator tree, where L is the least
* common ancestor of A and B in the post-dominator tree (L will be either A itself or
* the parent of A.).
*/
List<Block> bs = this.m_blockCFG.getSuccsOf(a);
for (Iterator<Block> bItr = bs.iterator(); bItr.hasNext(); ) {
List<Block> dependents = new ArrayList<Block>();
Block b = bItr.next();
if (b.equals(a))
throw new RuntimeException("PDG construction: A and B are not supposed to be the same node!");
DominatorNode<Block> aDode = pdom.getDode(a);
DominatorNode<Block> bDode = pdom.getDode(b);
// If B post-dominates A, go to the next successor.
if (pdom.isDominatorOf(bDode, aDode))
continue;
// FIXME: what if the parent is null?!!
DominatorNode<Block> aParentDode = aDode.getParent();
DominatorNode<Block> dode = bDode;
while (dode != aParentDode) {
dependents.add((Block) dode.getGode());
// This occurs if the CFG is multi-tailed and therefore the pdom is a forest.
if (dode.getParent() == null)
// throw new RuntimeException("parent dode in pdom is null: dode is " + aDode);
break;
dode = dode.getParent();
}
// first make A's pdg node be a conditional (predicate) pdgnode, if it's not already.
if (pdgNodeOfA.getAttrib() != PDGNode.Attribute.CONDHEADER) {
PDGNode oldA = pdgNodeOfA;
pdgNodeOfA = new ConditionalPDGNode(pdgNodeOfA);
this.replaceInGraph(pdgNodeOfA, oldA);
pdgnode.removeDependent(oldA);
this.m_obj2pdgNode.put(a, pdgNodeOfA);
pdgnode.addDependent(pdgNodeOfA);
pdgNodeOfA.setAttrib(PDGNode.Attribute.CONDHEADER);
curNodeInRegion = pdgNodeOfA;
}
List<Block> copyOfDependents = new ArrayList<Block>();
copyOfDependents.addAll(dependents);
// First, add the dependency for B and its corresponding region.
Region regionOfB = block2region.get(b);
PDGNode pdgnodeOfBRegion = null;
if (!this.m_obj2pdgNode.containsKey(regionOfB)) {
pdgnodeOfBRegion = new PDGNode(regionOfB, PDGNode.Type.REGION);
this.addNode(pdgnodeOfBRegion);
this.m_obj2pdgNode.put(regionOfB, pdgnodeOfBRegion);
} else
pdgnodeOfBRegion = this.m_obj2pdgNode.get(regionOfB);
// set the region hierarchy
regionOfB.setParent(r);
r.addChildRegion(regionOfB);
// add the dependency edges
this.addEdge(pdgNodeOfA, pdgnodeOfBRegion, "dependency");
pdgNodeOfA.addDependent(pdgnodeOfBRegion);
if (!processedRegions.contains(regionOfB)) {
regions2process.add(regionOfB);
}
// now remove b and all the nodes in the same weak region from the list of dependents
copyOfDependents.remove(b);
copyOfDependents.removeAll(regionOfB.getBlocks());
while (!copyOfDependents.isEmpty()) {
Block depB = copyOfDependents.remove(0);
Region rdepB = block2region.get(depB);
/*
* Actually, there are cases when depB is not the header of a loop and therefore would not dominate the current node
* (A) and therefore might not have been created yet. This has happened when an inner loop breaks out of the outer
* loop but could have other cases too.
*/
PDGNode depBPDGNode = this.m_obj2pdgNode.get(depB);
if (depBPDGNode == null) {
// First, add the dependency for depB and its corresponding region.
PDGNode pdgnodeOfdepBRegion = null;
if (!this.m_obj2pdgNode.containsKey(rdepB)) {
pdgnodeOfdepBRegion = new PDGNode(rdepB, PDGNode.Type.REGION);
this.addNode(pdgnodeOfdepBRegion);
this.m_obj2pdgNode.put(rdepB, pdgnodeOfdepBRegion);
} else
pdgnodeOfdepBRegion = this.m_obj2pdgNode.get(rdepB);
// set the region hierarchy
rdepB.setParent(regionOfB);
regionOfB.addChildRegion(rdepB);
// add the dependency edges
this.addEdge(pdgnodeOfBRegion, pdgnodeOfdepBRegion, "dependency");
pdgnodeOfBRegion.addDependent(pdgnodeOfdepBRegion);
if (!processedRegions.contains(rdepB)) {
regions2process.add(rdepB);
}
// now remove all the nodes in the same weak region from the list of dependents
copyOfDependents.removeAll(rdepB.getBlocks());
continue;
}
/**
* If all the nodes in the weak region of depB are dependent on A, then add
* an edge from the region of B to the region of depB.
*
* else, a new region has to be created to contain the dependences of depB, if
* not already created.
*/
if (dependents.containsAll(rdepB.getBlocks())) {
/*
* Just add an edge to the pdg node of the existing depB region.
*
*/
// add the dependency edges
// First, add the dependency for depB and its corresponding region.
PDGNode pdgnodeOfdepBRegion = null;
if (!this.m_obj2pdgNode.containsKey(rdepB)) {
pdgnodeOfdepBRegion = new PDGNode(rdepB, PDGNode.Type.REGION);
this.addNode(pdgnodeOfdepBRegion);
this.m_obj2pdgNode.put(rdepB, pdgnodeOfdepBRegion);
} else
pdgnodeOfdepBRegion = this.m_obj2pdgNode.get(rdepB);
// set the region hierarchy
// Do not set this because the region was created before so must have the
// proper parent already.
// rdepB.setParent(regionOfB);
// regionOfB.addChildRegion(rdepB);
this.addEdge(pdgnodeOfBRegion, pdgnodeOfdepBRegion, "dependency");
pdgnodeOfBRegion.addDependent(pdgnodeOfdepBRegion);
if (!processedRegions.contains(rdepB)) {
regions2process.add(rdepB);
}
// now remove all the nodes in the same weak region from the list of dependents
copyOfDependents.removeAll(rdepB.getBlocks());
continue;
} else {
PDGNode predPDGofdepB = (PDGNode) this.getPredsOf(depBPDGNode).get(0);
assert (this.m_obj2pdgNode.containsKey(rdepB));
PDGNode pdgnodeOfdepBRegion = this.m_obj2pdgNode.get(rdepB);
// If the loop header has not been separated from its weak region yet
if (predPDGofdepB == pdgnodeOfdepBRegion) {
/*
* Create a new region to represent the whole loop. In fact, this is a strong
* region as opposed to the weak regions that were created in the RegionAnalysis.
* This strong region only contains the header of the loop, A, and is dependent
* on it. Also, A is dependent on this strong region as well.
*/
Region newRegion = new Region(this.m_strongRegionStartID++, topLevelRegion.getSootMethod(), topLevelRegion.getSootClass(), this.m_cfg);
newRegion.add(depB);
this.m_strongRegions.add(newRegion);
// toBeRemoved.add(depB);
List<Block> blocks2BRemoved;
if (toBeRemoved.contains(predPDGofdepB))
blocks2BRemoved = toBeRemoved.get(predPDGofdepB);
else {
blocks2BRemoved = new ArrayList<Block>();
toBeRemoved.put(rdepB, blocks2BRemoved);
}
blocks2BRemoved.add(depB);
PDGNode newpdgnode = new LoopedPDGNode(newRegion, PDGNode.Type.REGION, depBPDGNode);
this.addNode(newpdgnode);
this.m_obj2pdgNode.put(newRegion, newpdgnode);
newpdgnode.setAttrib(PDGNode.Attribute.LOOPHEADER);
depBPDGNode.setAttrib(PDGNode.Attribute.LOOPHEADER);
this.removeEdge(pdgnodeOfdepBRegion, depBPDGNode, "dependency");
pdgnodeOfdepBRegion.removeDependent(depBPDGNode);
this.addEdge(pdgnodeOfdepBRegion, newpdgnode, "dependency");
this.addEdge(newpdgnode, depBPDGNode, "dependency");
pdgnodeOfdepBRegion.addDependent(newpdgnode);
newpdgnode.addDependent(depBPDGNode);
// If a is dependent on itself (simple loop)
if (depB == a) {
PDGNode loopBodyPDGNode = (PDGNode) this.getSuccsOf(depBPDGNode).get(0);
this.addEdge(depBPDGNode, newpdgnode, "dependency-back");
((LoopedPDGNode) newpdgnode).setBody(loopBodyPDGNode);
depBPDGNode.addBackDependent(newpdgnode);
// This is needed to correctly adjust the prev/next pointers for the new loop node. We should not need
// to adjust the old loop header node because the prev/next should not have been set previously for it.
curNodeInRegion = newpdgnode;
} else {
// this is a back-dependency
pdgnodeOfBRegion.addBackDependent(newpdgnode);
this.addEdge(pdgnodeOfBRegion, newpdgnode, "dependency-back");
// DEtermine which dependent of the loop header is actually the loop body region
PDGNode loopBodyPDGNode = null;
List<PDGNode> successors = this.getSuccsOf(depBPDGNode);
Iterator<PDGNode> succItr = successors.iterator();
while (succItr.hasNext()) {
PDGNode succRPDGNode = succItr.next();
assert (succRPDGNode.getType() == PDGNode.Type.REGION);
Region succR = (Region) succRPDGNode.getNode();
Block h = succR.getBlocks().get(0);
DominatorNode<Block> hdode = dom.getDode(h);
DominatorNode<Block> adode = dom.getDode(a);
if (dom.isDominatorOf(hdode, adode)) {
loopBodyPDGNode = succRPDGNode;
break;
}
}
assert (loopBodyPDGNode != null);
((LoopedPDGNode) newpdgnode).setBody(loopBodyPDGNode);
PDGNode prev = depBPDGNode.getPrev();
if (prev != null) {
this.removeEdge(prev, depBPDGNode, "controlflow");
this.addEdge(prev, newpdgnode, "controlflow");
prev.setNext(newpdgnode);
newpdgnode.setPrev(prev);
depBPDGNode.setPrev(null);
}
PDGNode next = depBPDGNode.getNext();
if (next != null) {
this.removeEdge(depBPDGNode, next, "controlflow");
this.addEdge(newpdgnode, next, "controlflow");
newpdgnode.setNext(next);
next.setPrev(newpdgnode);
depBPDGNode.setNext(null);
}
}
} else {
/*
* The strong region for the header has already been created and its
* corresponding PDGNode exist. Just add the dependency edge.
*/
this.addEdge(pdgnodeOfBRegion, predPDGofdepB, "dependency-back");
// this is a back-dependency
pdgnodeOfBRegion.addBackDependent(predPDGofdepB);
}
}
}
}
/* If there is a previous node in this region, add a control flow edge to indicate the
* the correct direction of control flow in the region.
*/
if (prevPDGNodeInRegion != null) {
this.addEdge(prevPDGNodeInRegion, curNodeInRegion, "controlflow");
prevPDGNodeInRegion.setNext(curNodeInRegion);
curNodeInRegion.setPrev(prevPDGNodeInRegion);
}
prevPDGNodeInRegion = curNodeInRegion;
}
// remove all the blocks marked to be removed from the region (to change a weak region
// to a strong region.)
Enumeration<Region> itr1 = toBeRemoved.keys();
while (itr1.hasMoreElements()) {
Region region = itr1.nextElement();
Iterator<Block> blockItr = toBeRemoved.get(region).iterator();
while (blockItr.hasNext()) region.remove(blockItr.next());
}
}
}
use of soot.toolkits.graph.Block in project soot by Sable.
the class PDGRegion method getUnits.
public List<Unit> getUnits() {
if (this.m_units == null) {
this.m_units = new LinkedList<Unit>();
this.m_unit2pdgnode = new LinkedHashMap<Unit, PDGNode>();
for (Iterator<PDGNode> itr = this.iterator(); itr.hasNext(); ) {
PDGNode node = itr.next();
if (node.getType() == PDGNode.Type.REGION) {
// if(node.getAttrib() == PDGNode.Attribute.LOOPHEADER)
if (node instanceof LoopedPDGNode) {
LoopedPDGNode n = (LoopedPDGNode) node;
PDGNode header = n.getHeader();
Block headerBlock = (Block) header.getNode();
for (Iterator<Unit> itr1 = headerBlock.iterator(); itr1.hasNext(); ) {
Unit u = itr1.next();
((LinkedList<Unit>) this.m_units).addLast(u);
this.m_unit2pdgnode.put(u, header);
}
}
} else if (node.getType() == PDGNode.Type.CFGNODE) {
Block b = (Block) node.getNode();
for (Iterator<Unit> itr1 = b.iterator(); itr1.hasNext(); ) {
Unit u = itr1.next();
((LinkedList<Unit>) this.m_units).addLast(u);
this.m_unit2pdgnode.put(u, node);
}
} else
throw new RuntimeException("Exception in PDGRegion.getUnits: PDGNode's type is undefined!");
}
}
return this.m_units;
}
Aggregations