/* Soot - a J*va Optimization Framework * Copyright (C) 2003 Jerome Miecznikowski * * 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 soot.dava.toolkits.base.finders; import soot.*; import soot.dava.*; import java.util.*; import soot.util.*; import soot.dava.internal.asg.*; import soot.dava.internal.SET.*; public class LabeledBlockFinder implements FactFinder { public LabeledBlockFinder( Singletons.Global g ) {} public static LabeledBlockFinder v() { return G.v().soot_dava_toolkits_base_finders_LabeledBlockFinder(); } private final HashMap<SETNode,Integer> orderNumber = new HashMap(); public void find( DavaBody body, AugmentedStmtGraph asg, SETNode SET) throws RetriggerAnalysisException { Dava.v().log( "LabeledBlockFinder::find()"); Iterator bit = SET.get_Body().iterator(); while (bit.hasNext()) SET.find_SmallestSETNode((AugmentedStmt) bit.next()); SET.find_LabeledBlocks( this); } public void perform_ChildOrder( SETNode SETParent) { Dava.v().log( "LabeledBlockFinder::perform_ChildOrder()"); if (SETParent instanceof SETStatementSequenceNode) return; Iterator<IterableSet> sbit = SETParent.get_SubBodies().iterator(); while (sbit.hasNext()) { IterableSet body = sbit.next(); IterableSet children = SETParent.get_Body2ChildChain().get( body); HashSet<SETBasicBlock> touchSet = new HashSet<SETBasicBlock>(); IterableSet childOrdering = new IterableSet(); LinkedList worklist = new LinkedList(); List<SETBasicBlock> SETBasicBlocks = null; if (SETParent instanceof SETUnconditionalWhileNode) { SETNode startSETNode = ((SETUnconditionalWhileNode) SETParent).get_CharacterizingStmt().myNode; while (children.contains( startSETNode) == false) startSETNode = startSETNode.get_Parent(); SETBasicBlocks = build_Connectivity( SETParent, body, startSETNode); worklist.add( SETBasicBlock.get_SETBasicBlock( startSETNode)); } else if (SETParent instanceof SETTryNode) { SETNode startSETNode = null; Iterator bit = body.iterator(); find_entry_loop: while (bit.hasNext()) { AugmentedStmt as = (AugmentedStmt) bit.next(); Iterator pbit = as.cpreds.iterator(); while (pbit.hasNext()) if (body.contains( pbit.next()) == false) { startSETNode = as.myNode; break find_entry_loop; } } if (startSETNode == null) startSETNode = ((SETTryNode) SETParent).get_EntryStmt().myNode; while (children.contains( startSETNode) == false) startSETNode = startSETNode.get_Parent(); SETBasicBlocks = build_Connectivity( SETParent, body, startSETNode); worklist.add( SETBasicBlock.get_SETBasicBlock( startSETNode)); } else { SETBasicBlocks = build_Connectivity( SETParent, body, null); Iterator cit = children.iterator(); while (cit.hasNext()) { SETNode child = (SETNode) cit.next(); if (child.get_Predecessors().isEmpty()) worklist.add( SETBasicBlock.get_SETBasicBlock( child)); } } while (worklist.isEmpty() == false) { SETBasicBlock sbb = (SETBasicBlock) worklist.removeFirst(); // extract and append the basic block to child ordering Iterator bit = sbb.get_Body().iterator(); while (bit.hasNext()) childOrdering.addLast( bit.next()); touchSet.add( sbb); /* ************************************************ * * Basic orderer. */ TreeSet sortedSuccessors = new TreeSet(); Iterator sit = sbb.get_Successors().iterator(); SETBasicBlock_successor_loop: while (sit.hasNext()) { SETBasicBlock ssbb = (SETBasicBlock) sit.next(); if (touchSet.contains( ssbb)) continue; Iterator psit = ssbb.get_Predecessors().iterator(); while (psit.hasNext()) if (touchSet.contains( psit.next()) == false) continue SETBasicBlock_successor_loop; sortedSuccessors.add( ssbb); } sit = sortedSuccessors.iterator(); while (sit.hasNext()) worklist.addFirst( sit.next()); /* * End of Basic orderer. * ************************************************ */ } int count = 0; Iterator it = childOrdering.iterator(); while (it.hasNext()) orderNumber.put( (SETNode) it.next(), new Integer( count++)); children.clear(); children.addAll( childOrdering); } } private List<SETBasicBlock> build_Connectivity( SETNode SETParent, IterableSet body, SETNode startSETNode) { Dava.v().log( "LabeledBlockFinder::build_Connectivity()"); IterableSet children = SETParent.get_Body2ChildChain().get( body); /* * First task: establish the connectivity between the children of the current node. */ // look through all the statements in the current SETNode Iterator it = body.iterator(); while (it.hasNext()) { AugmentedStmt as = (AugmentedStmt) it.next(); // for each statement, examine each of it's successors Iterator sit = as.csuccs.iterator(); while (sit.hasNext()) { AugmentedStmt sas = (AugmentedStmt) sit.next(); if (body.contains( sas)) { // get the child nodes that contain the source and destination statements SETNode srcNode = as.myNode; SETNode dstNode = sas.myNode; while (children.contains( srcNode) == false) srcNode = srcNode.get_Parent(); while (children.contains( dstNode) == false) dstNode = dstNode.get_Parent(); if (srcNode == dstNode) continue; // hook up the src and dst nodes if (srcNode.get_Successors().contains( dstNode) == false) srcNode.get_Successors().add( dstNode); if (dstNode.get_Predecessors().contains( srcNode) == false) dstNode.get_Predecessors().add( srcNode); } } } Dava.v().log( "LabeledBlockFinder::build_Connectivity() - built connectivity"); /* * Second task: build the basic block graph between the node. */ // first create the basic blocks LinkedList<SETBasicBlock> basicBlockList = new LinkedList<SETBasicBlock>(); Iterator cit = children.iterator(); while (cit.hasNext()) { SETNode child = (SETNode) cit.next(); if (SETBasicBlock.get_SETBasicBlock( child) != null) continue; // build a basic block for every node with != 1 predecessor SETBasicBlock basicBlock = new SETBasicBlock(); while (child.get_Predecessors().size() == 1) { if ((startSETNode != null) && (child == startSETNode)) break; SETNode prev = (SETNode) child.get_Predecessors().getFirst(); if ((SETBasicBlock.get_SETBasicBlock( prev) != null) || (prev.get_Successors().size() != 1)) break; child = prev; } basicBlock.add( child); while (child.get_Successors().size() == 1) { child = (SETNode) child.get_Successors().getFirst(); if ((SETBasicBlock.get_SETBasicBlock( child) != null) || (child.get_Predecessors().size() != 1)) break; basicBlock.add( child); } basicBlockList.add( basicBlock); } Dava.v().log( "LabeledBlockFinder::build_Connectivity() - created basic blocks"); // next build the connectivity between the nodes of the basic block graph Iterator<SETBasicBlock> bblit = basicBlockList.iterator(); while (bblit.hasNext()) { SETBasicBlock sbb = bblit.next(); SETNode entryNode = sbb.get_EntryNode(); Iterator pit = entryNode.get_Predecessors().iterator(); while (pit.hasNext()) { SETNode psn = (SETNode) pit.next(); SETBasicBlock psbb = SETBasicBlock.get_SETBasicBlock( psn); if (sbb.get_Predecessors().contains( psbb) == false) sbb.get_Predecessors().add( psbb); if (psbb.get_Successors().contains( sbb) == false) psbb.get_Successors().add( sbb); } } Dava.v().log( "LabeledBlockFinder::build_Connectivity() - done"); return basicBlockList; } public void find_LabeledBlocks( SETNode SETParent) { Dava.v().log( "LabeledBlockFinder::find_LabeledBlocks()"); Iterator<IterableSet> sbit = SETParent.get_SubBodies().iterator(); while (sbit.hasNext()) { IterableSet curBody = sbit.next(); IterableSet children = SETParent.get_Body2ChildChain().get( curBody); Iterator it = children.snapshotIterator(); if (it.hasNext()) { SETNode curNode = (SETNode) it.next(), prevNode = null; // Look through all the children of the current SET node. while (it.hasNext()) { prevNode = curNode; curNode = (SETNode) it.next(); AugmentedStmt entryStmt = curNode.get_EntryStmt(); SETNode minNode = null; boolean build = false; // For each SET node, check the edges that come into it. Iterator pit = entryStmt.cpreds.iterator(); while (pit.hasNext()) { AugmentedStmt pas = (AugmentedStmt) pit.next(); if (curBody.contains( pas) == false) // will happen with do-while loops continue; SETNode srcNode = pas.myNode; while (children.contains( srcNode) == false) srcNode = srcNode.get_Parent(); if (srcNode == curNode) continue; if (srcNode != prevNode) { build = true; if ((minNode == null) || (orderNumber.get( srcNode).intValue() < orderNumber.get( minNode).intValue())) minNode = srcNode; } } if (build) { IterableSet labeledBlockBody = new IterableSet(); Iterator cit = children.iterator( minNode); while (cit.hasNext()) { SETNode child = (SETNode) cit.next(); if (child == curNode) break; labeledBlockBody.addAll( child.get_Body()); } SETLabeledBlockNode slbn = new SETLabeledBlockNode( labeledBlockBody); orderNumber.put( slbn, orderNumber.get( minNode)); cit = children.snapshotIterator( minNode); while (cit.hasNext()) { SETNode child = (SETNode) cit.next(); if (child == curNode) break; SETParent.remove_Child( child, children ); slbn.add_Child( child, slbn.get_Body2ChildChain().get( slbn.get_SubBodies().get(0))); } SETParent.insert_ChildBefore( slbn, curNode, children); } } } } } }