Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /* Soot - a J*va Optimization Framework
   * Copyright (C) 1999 Patrice Pominville, Raja Vallee-Rai
   *
   * 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.
  */
 
 /*
  * Modified by the Sable Research Group and others 1997-2004.
  * See the 'credits' file distributed with Soot for the complete list of
  * contributors.  (Soot is distributed at http://www.sable.mcgill.ca/soot)
  */
 
 
 package soot.toolkits.graph;
 
 import java.util.*;
 
 import soot.*;
 

Represents a CFG where the nodes are Blocks and the edges are derived from control flow. Control flow associated with exceptions is taken into account: when a soot.Unit may throw an exception that is caught by a soot.Trap within the Body, the excepting Unit starts a new basic block (Units do not start a new block when all the exceptions they might throw would escape the method without being caught).

 
 
 public class ExceptionalBlockGraph extends BlockGraph implements ExceptionalGraph<Block>
 {
     // Maps for distinguishing exceptional and unexceptional control flow.
     // We follow two conventions to save space (and runtime, if no client ever 
     // asks for the exceptional information):  if the graph contains no
     // exceptional edges (e.g. there are no traps in the method) we leave
     // all these map references as NULL, while if an individual block has only 
     // unexceptional successors or predecessors, it is not added to the 
     // relevant map. When the access methods are asked about such blocks, 
     // they return empty lists for the exceptional predecessors and successors,
     // and the complete list of predecessors or successors for 
     // the unexceptional predecessors and successors.
 
     // When the graph has no traps (thus no exceptional CFG edges); we cache the
     // throwAnalysis for generating ExceptionDests on demand.  If there
     // are traps, throwAnalysis remains null.
     ThrowAnalysis throwAnalysis ;

    

Constructs an ExceptionalBlockGraph for the blocks found by partitioning the the units of the provided Body instance into basic blocks.

Note that this constructor builds an ExceptionalUnitGraph internally when splitting body's soot.Units into Blocks. Callers who already have an ExceptionalUnitGraph to hand can use the constructor taking an ExceptionalUnitGraph as a parameter, as a minor optimization.

Parameters:
body The underlying body we want to make a graph for.
 
     public ExceptionalBlockGraph(Body body)
     {
         this(new ExceptionalUnitGraph(body));
     }


    
Constructs a graph for the blocks found by partitioning the the soot.Units in an ExceptionalUnitGraph.

Parameters:
unitGraph The ExceptionalUnitGraph whose Units are to be split into blocks.
 
     public ExceptionalBlockGraph(ExceptionalUnitGraph unitGraph)
     {
         super(unitGraph);
    }


    
This implementation calls the inherited implementation to split units into blocks, before adding the distinctions between exceptional and unexceptional control flow.

Parameters:
Returns:
    protected Map<Unit,BlockbuildBlocks(Set<UnitleadersUnitGraph uncastUnitGraph) {
	ExceptionalUnitGraph unitGraph = (ExceptionalUnitGraphuncastUnitGraph;
	Map<Unit,BlockunitToBlock = super.buildBlocks(leadersunitGraph);
	if (unitGraph.getBody().getTraps().size() == 0) {
	    // All exceptions escape the method.  Cache the ThrowAnalysis
	    // to respond to getExceptionDests() on demand.
	     = unitGraph.getThrowAnalysis();
	    if ( == null) {
		throw new IllegalStateException("ExceptionalUnitGraph lacked a cached ThrowAnalysis for a Body with no Traps.");
	    }
else {
	    int initialMapSize = (.size() * 2) / 3;
	     = new HashMap<BlockList<Block>>(initialMapSize);
	     = new HashMap<BlockList<Block>>(initialMapSize);
	     = new HashMap<BlockList<Block>>(initialMapSize);
	     = new HashMap<BlockList<Block>>(initialMapSize);
	    for (Iterator<BlockblockIt = .iterator(); blockIt.hasNext(); ) {
		Block block = blockIt.next();
		Unit blockHead = block.getHead();
		List<UnitexceptionalPredUnits = unitGraph.getExceptionalPredsOf(blockHead);
		if (exceptionalPredUnits.size() != 0) {
		    List<BlockexceptionalPreds = mappedValues(exceptionalPredUnits,
							 unitToBlock);
		    exceptionalPreds = Collections.unmodifiableList(exceptionalPreds);
		    .put(blockexceptionalPreds);
		    List<UnitunexceptionalPredUnits = unitGraph.getUnexceptionalPredsOf(blockHead);
		    List<BlockunexceptionalPreds = null;
		    if (unexceptionalPredUnits.size() == 0) {
			unexceptionalPreds = Collections.emptyList();
		    } else {
			unexceptionalPreds = mappedValues(unexceptionalPredUnits,
							  unitToBlock);
			unexceptionalPreds = Collections.unmodifiableList(unexceptionalPreds);
		    }
		    .put(blockunexceptionalPreds);
		}
		Unit blockTail = block.getTail();
		List<UnitexceptionalSuccUnits = unitGraph.getExceptionalSuccsOf(blockTail);
		if (exceptionalSuccUnits.size() != 0) {
		    List<BlockexceptionalSuccs = mappedValues(exceptionalSuccUnits,
							 unitToBlock);
		    exceptionalSuccs = Collections.unmodifiableList(exceptionalSuccs);
		      .put(blockexceptionalSuccs);
		    List<UnitunexceptionalSuccUnits = unitGraph.getUnexceptionalSuccsOf(blockTail);
		    List<BlockunexceptionalSuccs = null;
		    if (unexceptionalSuccUnits.size() == 0) {
			unexceptionalSuccs = Collections.emptyList();
		    } else {
			unexceptionalSuccs = mappedValues(unexceptionalSuccUnits,
							  unitToBlock);
			unexceptionalSuccs = Collections.unmodifiableList(unexceptionalSuccs);
		    }
		    .put(block,unexceptionalSuccs);
		}
	    }
	     = buildExceptionDests(unitGraphunitToBlock);
	}
	return unitToBlock;
    }


    
Utility method which, given a java.util.List of objects and a java.util.Map where those objects appear as keys, returns a List of the values to which the keys map, in the corresponding order.

Parameters:
keys the keys to be looked up.
keyToValue the map in which to look up the keys.
Throws:
java.lang.IllegalStateException if one of the elements in keys does not appear in keyToValue
    private <K,V> List<V> mappedValues(List<K> keysMap<K,V> keyToValue) {
	List<V> result = new ArrayList<V>(keys.size());
	for (Iterator<K> it = keys.iterator(); it.hasNext(); ) {
	    K key = it.next();
	    V value = keyToValue.get(key);
	    if (value == null) {
		throw new IllegalStateException("No value corresponding to key: " + key.toString());
	    }
	    result.add(value);
	}
	return result;
    }
				    Map<Unit,BlockunitToBlock) {
	Map<BlockCollection<ExceptionDest>> result = new HashMap<BlockCollection<ExceptionDest>>(.size() * 2 + 1, 0.7f);
	for (Iterator<BlockblockIt = .iterator(); blockIt.hasNext(); ) {
	    Block block = blockIt.next();
	    result.put(blockcollectDests(blockunitGraphunitToBlock));
	}
	return result;
    }


    
Utility method which, given a Block and the ExceptionalUnitGraph from which it was constructed, returns the ExceptionalBlockGraph.ExceptionDests representing the exceptions which may be thrown by units in the block.

Parameters:
block the Block whose exceptions are to be collected.
unitGraph the ExceptionalUnitGraph from which this graph is constructed.
unitToBlock a java.util.Map from the units which are block heads or tails to the blocks that they belong to.
Returns:
a java.util.Collection of ExceptionalBlockGraph.ExceptionDests representing the exceptions that may be thrown by this block, together with their catchers.
    private Collection<ExceptionDestcollectDests(Block blockExceptionalUnitGraph unitGraph,
				    Map<Unit,BlockunitToBlock) {
	Unit blockHead = block.getHead();
	Unit blockTail = block.getTail();
	ArrayList<ExceptionDestblocksDests = null;
	ThrowableSet escapingThrowables = ThrowableSet.Manager.v().;
	Map<TrapThrowableSettrapToThrowables = null;	// Don't allocate unless we need it.
	int caughtCount = 0;
	for (Iterator<UnitunitIt = block.iterator(); unitIt.hasNext(); ) {
	    Unit unit = (UnitunitIt.next();
	    Collection<ExceptionalUnitGraph.ExceptionDestunitDests = unitGraph.getExceptionDests(unit);
	    if (unitDests.size() != 1 && unit != blockHead && unit != blockTail) {
		throw new IllegalStateException("Multiple ExceptionDests associated with a unit which does not begin or end its block.");
	    }
	    for (Iterator<ExceptionalUnitGraph.ExceptionDestdestIt = unitDests.iterator(); destIt.hasNext(); ) {
		    = destIt.next();
		if (unitDest.getTrap() == null) {
		    try {
			escapingThrowables = escapingThrowables.add(unitDest.getThrowables());
			if (escapingThrowables != ThrowableSet.Manager.v().) {
			    // Return multiple escaping ExceptionDests,
			    // since ThrowableSet's limitations do not permit us
			    // to add all the escaping type descriptions together.
			    if (blocksDests == null) {
				blocksDests = new ArrayList<ExceptionDest>(10);
			    }
			    blocksDests.add(new ExceptionDest(null
							      escapingThrowables,
							      null));
			}
			escapingThrowables = unitDest.getThrowables();
		    }
else {
		    if (unit != blockHead && unit != blockTail) {
			// Assertion failure.
			throw new IllegalStateException("Unit " 
unit.toString() 
" is not a block head or tail, yet it throws " 
unitDest.getThrowables() 
" to "
unitDest.getTrap());
		    }
		    caughtCount++;
		    if (trapToThrowables == null) {
			trapToThrowables = new HashMap<TrapThrowableSet>(unitDests.size() * 2);
		    }
		    Trap trap = unitDest.getTrap();
		    ThrowableSet throwables = trapToThrowables.get(trap);
		    if (throwables == null) {
			throwables = unitDest.getThrowables();
		    } else {
			throwables = throwables.add(unitDest.getThrowables());
		    }
		    trapToThrowables.put(trapthrowables);
		}
	    }
	}
	if (blocksDests == null) {
	    blocksDests = new ArrayList<ExceptionDest>(caughtCount + 1);
else {
	    blocksDests.ensureCapacity(blocksDests.size() + caughtCount);
	}
	if (escapingThrowables != ThrowableSet.Manager.v().) {
	    ExceptionDest escapingDest = new ExceptionDest(nullescapingThrowables
							   null);
	    blocksDests.add(escapingDest);
	}
	if (trapToThrowables != null) {
	    for (Map.Entry<Trap,ThrowableSetentry : trapToThrowables.entrySet()) {
		Trap trap = entry.getKey();
		Block trapBlock = (BlockunitToBlock.get(trap.getHandlerUnit());
		if (trapBlock == null) {
		    throw new IllegalStateException("catching unit is not recorded as a block leader.");
		}
		ThrowableSet throwables = entry.getValue();
		ExceptionDest blockDest = new ExceptionDest(trapthrowablestrapBlock);
		blocksDests.add(blockDest);
	    }
	}
	return blocksDests;
    }
								  
    public List<BlockgetUnexceptionalPredsOf(Block b) {
	if (( == null
	    || (! .containsKey(b))) {
	    Block block = (Blockb;
	    return block.getPreds();
else {
	    return .get(b);
	}
    }
    public List<BlockgetUnexceptionalSuccsOf(Block b) {
	if (( == null
	    || (! .containsKey(b))) {
	    Block block = (Blockb;
	    return block.getSuccs();
else {
	    return .get(b);
	}
    }
    public List<BlockgetExceptionalPredsOf(Block  b) {
	if ( == null ||
	    return Collections.emptyList();
else {
	    return .get(b);
	}
    }
    public List<BlockgetExceptionalSuccsOf(Block b) {
	if ( == null ||
	    return Collections.emptyList();
else {
	    return .get(b);
	}
    }
	if ( == null) {
	    Block block = (Blockb;
	    Collection<ExceptionDestresult = new ArrayList<ExceptionDest>(1);
	    ThrowableSet throwables = ThrowableSet.Manager.v().;
	    for (Iterator<UnitunitIt = block.iterator(); unitIt.hasNext(); ) {
		Unit unit = unitIt.next();
		throwables = throwables.add(.mightThrow(unit));
	    }
	    result.add(new ExceptionalBlockGraph.ExceptionDest(nullthrowables,
							       null));
	    return result;
else {
	    return .get(b);
	}
    }
    public static class ExceptionDest implements ExceptionalGraph.ExceptionDest<Block> {
	private Trap trap;
	private Block handler;
	protected ExceptionDest(Trap trapThrowableSet throwablesBlock handler) {
	    this. = trap;
	    this. = throwables;
	    this. = handler;
	}
	public Trap getTrap() {
	    return ;
	}
	    return ;
	}
	public Block getHandlerNode() {
	    return ;
	}
	public String toString() {
	    StringBuffer buf = new StringBuffer();
	    buf.append(.toString());
	    buf.append(" -> ");
	    if ( == null) {
		buf.append("(escapes)");
	    } else {
		buf.append("handler: ");
	    }
	    return buf.toString();
	}
    }
New to GrepCode? Check out our FAQ X