/ded/soot/soot-2.3.0/src/soot/toolkits/scalar/ForwardBranchedFlowAnalysis.java
Java | 325 lines | 207 code | 55 blank | 63 comment | 30 complexity | 1b72320e59df5e9d716866143b94e276 MD5 | raw file
Possible License(s): GPL-3.0, Apache-2.0, GPL-2.0
- /* Soot - a J*va Optimization Framework
- * Copyright (C) 1997-2000 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-2000.
- * See the 'credits' file distributed with Soot for the complete list of
- * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
- */
- /*
- 2000, March 20 - Updated code provided by Patrick Lam
- <plam@sable.mcgill.ca>
- from 1.beta.4.dev.60
- to 1.beta.6.dev.34
- Plus some bug fixes.
- -- Janus <janus@place.org>
- KNOWN LIMITATION: the analysis doesn't handle traps since traps
- handler statements have predecessors, but they
- don't have the trap handler as successor. This
- might be a limitation of the CompleteUnitGraph
- tho.
- */
- package soot.toolkits.scalar;
- import soot.*;
- import soot.toolkits.graph.*;
- import soot.util.*;
- import java.util.*;
- import soot.toolkits.graph.interaction.*;
- import soot.options.*;
- /** Abstract class providing an engine for branched forward flow analysis.
- * WARNING: This does not handle exceptional flow as branches!
- * */
- public abstract class ForwardBranchedFlowAnalysis<A> extends BranchedFlowAnalysis<Unit, A>
- {
- public ForwardBranchedFlowAnalysis(UnitGraph graph)
- {
- super(graph);
- }
- protected boolean isForward()
- {
- return true;
- }
- // Accumulate the previous afterFlow sets.
- private void accumulateAfterFlowSets(Unit s, A[] flowRepositories, List<Object> previousAfterFlows)
- {
- int repCount = 0;
-
- previousAfterFlows.clear();
- if (s.fallsThrough())
- {
- copy(unitToAfterFallFlow.get(s).get(0), flowRepositories[repCount]);
- previousAfterFlows.add(flowRepositories[repCount++]);
- }
-
- if (s.branches())
- {
- List<A> l = (unitToAfterBranchFlow.get(s));
- Iterator<A> it = l.iterator();
- while (it.hasNext())
- {
- A fs = (it.next());
- copy(fs, flowRepositories[repCount]);
- previousAfterFlows.add(flowRepositories[repCount++]);
- }
- }
- } // end accumulateAfterFlowSets
- protected void doAnalysis()
- {
- final Map<Unit, Integer> numbers = new HashMap<Unit, Integer>();
- List orderedUnits = new PseudoTopologicalOrderer().newList(graph,false);
- {
- int i = 1;
- for( Iterator uIt = orderedUnits.iterator(); uIt.hasNext(); ) {
- final Unit u = (Unit) uIt.next();
- numbers.put(u, new Integer(i));
- i++;
- }
- }
- TreeSet<Unit> changedUnits = new TreeSet<Unit>( new Comparator() {
- public int compare(Object o1, Object o2) {
- Integer i1 = numbers.get(o1);
- Integer i2 = numbers.get(o2);
- return (i1.intValue() - i2.intValue());
- }
- } );
- Map<Unit, ArrayList> unitToIncomingFlowSets = new HashMap<Unit, ArrayList>(graph.size() * 2 + 1, 0.7f);
- List heads = graph.getHeads();
- int numNodes = graph.size();
- int numComputations = 0;
- int maxBranchSize = 0;
-
- // initialize unitToIncomingFlowSets
- {
- Iterator it = graph.iterator();
- while (it.hasNext())
- {
- Unit s = (Unit) it.next();
- unitToIncomingFlowSets.put(s, new ArrayList());
- }
- }
- // Set initial values and nodes to visit.
- // WARNING: DO NOT HANDLE THE CASE OF THE TRAPS
- {
- Chain sl = ((UnitGraph)graph).getBody().getUnits();
- Iterator it = graph.iterator();
- while(it.hasNext())
- {
- Unit s = (Unit) it.next();
- changedUnits.add(s);
- unitToBeforeFlow.put(s, newInitialFlow());
- if (s.fallsThrough())
- {
- ArrayList<A> fl = new ArrayList<A>();
- fl.add((newInitialFlow()));
- unitToAfterFallFlow.put(s, fl);
- Unit succ=(Unit) sl.getSuccOf(s);
- // it's possible for someone to insert some (dead)
- // fall through code at the very end of a method body
- if(succ!=null) {
- List<Object> l = (unitToIncomingFlowSets.get(sl.getSuccOf(s)));
- l.addAll(fl);
- }
- }
- else
- unitToAfterFallFlow.put(s, new ArrayList<A>());
- if (s.branches())
- {
- ArrayList<A> l = new ArrayList<A>();
- List<A> incList;
- Iterator boxIt = s.getUnitBoxes().iterator();
- while (boxIt.hasNext())
- {
- A f = (newInitialFlow());
- l.add(f);
- Unit ss = ((UnitBox) (boxIt.next())).getUnit();
- incList = (unitToIncomingFlowSets.get(ss));
-
- incList.add(f);
- }
- unitToAfterBranchFlow.put(s, l);
- }
- else
- unitToAfterBranchFlow.put(s, new ArrayList<A>());
- if (s.getUnitBoxes().size() > maxBranchSize)
- maxBranchSize = s.getUnitBoxes().size();
- }
- }
- // Feng Qian: March 07, 2002
- // init entry points
- {
- Iterator<Unit> it = heads.iterator();
- while (it.hasNext()) {
- Unit s = it.next();
- // this is a forward flow analysis
- unitToBeforeFlow.put(s, entryInitialFlow());
- }
- }
- if (treatTrapHandlersAsEntries())
- {
- Iterator trapIt = ((UnitGraph)graph).getBody().
- getTraps().iterator();
- while(trapIt.hasNext()) {
- Trap trap = (Trap) trapIt.next();
- Unit handler = trap.getHandlerUnit();
- unitToBeforeFlow.put(handler, entryInitialFlow());
- }
- }
- // Perform fixed point flow analysis
- {
- List<Object> previousAfterFlows = new ArrayList<Object>();
- List<Object> afterFlows = new ArrayList<Object>();
- A[] flowRepositories = (A[]) new Object[maxBranchSize+1];
- for (int i = 0; i < maxBranchSize+1; i++)
- flowRepositories[i] = newInitialFlow();
- A[] previousFlowRepositories = (A[])new Object[maxBranchSize+1];
- for (int i = 0; i < maxBranchSize+1; i++)
- previousFlowRepositories[i] = newInitialFlow();
- while(!changedUnits.isEmpty())
- {
- A beforeFlow;
- Unit s = changedUnits.first();
- changedUnits.remove(s);
- boolean isHead = heads.contains(s);
- accumulateAfterFlowSets(s, previousFlowRepositories, previousAfterFlows);
- // Compute and store beforeFlow
- {
- List<A> preds = unitToIncomingFlowSets.get(s);
- beforeFlow = unitToBeforeFlow.get(s);
- if(preds.size() == 1)
- copy(preds.get(0), beforeFlow);
- else if(preds.size() != 0)
- {
- Iterator<A> predIt = preds.iterator();
- copy(predIt.next(), beforeFlow);
- while(predIt.hasNext())
- {
- A otherBranchFlow = predIt.next();
- A newBeforeFlow = newInitialFlow();
- merge(beforeFlow, otherBranchFlow, newBeforeFlow);
- copy(newBeforeFlow, beforeFlow);
- }
- }
- if(isHead && preds.size() != 0)
- merge(beforeFlow, entryInitialFlow());
- }
- // Compute afterFlow and store it.
- {
- ArrayList<A> afterFallFlow = unitToAfterFallFlow.get(s);
- ArrayList<A> afterBranchFlow = unitToAfterBranchFlow.get(s);
- if (Options.v().interactive_mode()){
- A savedFlow = newInitialFlow();
- copy(beforeFlow, savedFlow);
- FlowInfo fi = new FlowInfo(savedFlow, s, true);
- if (InteractionHandler.v().getStopUnitList() != null && InteractionHandler.v().getStopUnitList().contains(s)){
- InteractionHandler.v().handleStopAtNodeEvent(s);
- }
- InteractionHandler.v().handleBeforeAnalysisEvent(fi);
- }
- flowThrough(beforeFlow, s, (List) afterFallFlow, (List) afterBranchFlow);
- if (Options.v().interactive_mode()){
- ArrayList l = new ArrayList();
- if (!((List)afterFallFlow).isEmpty()){
- l.addAll((List)afterFallFlow);
- }
- if (!((List)afterBranchFlow).isEmpty()){
- l.addAll((List)afterBranchFlow);
- }
-
- /*if (s instanceof soot.jimple.IfStmt){
- l.addAll((List)afterFallFlow);
- l.addAll((List)afterBranchFlow);
- }
- else {
- l.addAll((List)afterFallFlow);
- }*/
- FlowInfo fi = new FlowInfo(l, s, false);
- InteractionHandler.v().handleAfterAnalysisEvent(fi);
- }
- numComputations++;
- }
- accumulateAfterFlowSets(s, flowRepositories, afterFlows);
- // Update queue appropriately
- if(!afterFlows.equals(previousAfterFlows))
- {
- Iterator succIt = graph.getSuccsOf(s).iterator();
- while(succIt.hasNext())
- {
- Unit succ = (Unit) succIt.next();
-
- changedUnits.add(succ);
- }
- }
- }
- }
-
- // G.v().out.println(graph.getBody().getMethod().getSignature() + " numNodes: " + numNodes +
- // " numComputations: " + numComputations + " avg: " + Main.truncatedOf((double) numComputations / numNodes, 2));
-
- Timers.v().totalFlowNodes += numNodes;
- Timers.v().totalFlowComputations += numComputations;
- } // end doAnalysis
- } // end class ForwardBranchedFlowAnalysis