All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.jimple.toolkits.scalar.EqualUsesAnalysis Maven / Gradle / Ivy

There is a newer version: 2.5.0-9
Show newest version
package soot.jimple.toolkits.scalar;

import soot.*;
import java.util.*;

import soot.toolkits.graph.*;
import soot.toolkits.scalar.*;
import soot.jimple.*;

// EqualUsesAnalysis written by Richard L. Halpert, 2006-12-04
// Determines if a set of uses of locals all use the same value
// whenever they occur together.  Can accept a set of boundary
// statements which define a region which, if exited, counts
// 
// The locals being used need not be the same

/**
 * @deprecated This class is buggy. Please use soot.jimple.toolkits.pointer.LocalMustAliasAnalysis instead.
 */
public class EqualUsesAnalysis extends ForwardFlowAnalysis
{
	// Provided by client
	Map stmtToLocal;
	Set useStmts;
	Collection useLocals;
	List boundaryStmts;

	// Calculated by flow analysis
	List redefStmts;
	Map firstUseToAliasSet;
	
	EqualLocalsAnalysis el;
	
	public EqualUsesAnalysis(UnitGraph g)
	{
		super(g);
		
		useStmts = null;
		useLocals = null;
		boundaryStmts = null;

		redefStmts = null;
		firstUseToAliasSet = null;
		
		// analysis is done on-demand, not now

		this.el= new EqualLocalsAnalysis(g); // also on-demand
	}

	public boolean areEqualUses(Stmt firstStmt, Local firstLocal, Stmt secondStmt, Local secondLocal)
	{
		Map stmtToLocal = new HashMap();
		stmtToLocal.put(firstStmt, firstLocal);
		stmtToLocal.put(secondStmt, secondLocal);
		return areEqualUses(stmtToLocal, new ArrayList());
	}
	
	public boolean areEqualUses(Stmt firstStmt, Local firstLocal, Stmt secondStmt, Local secondLocal, List boundaryStmts)
	{
		Map stmtToLocal = new HashMap();
		stmtToLocal.put(firstStmt, firstLocal);
		stmtToLocal.put(secondStmt, secondLocal);
		return areEqualUses(stmtToLocal, boundaryStmts);
	}
	
	public boolean areEqualUses(Map stmtToLocal)
	{
		return areEqualUses(stmtToLocal, new ArrayList());
	}
	
	public boolean areEqualUses(Map stmtToLocal, List boundaryStmts)
	{// You may optionally specify start and end statements... for if you're interested only in a certain part of the method
		this.stmtToLocal = stmtToLocal;
		this.useStmts = stmtToLocal.keySet();
		this.useLocals = stmtToLocal.values();
		this.boundaryStmts = boundaryStmts;
		this.redefStmts = new ArrayList();
		this.firstUseToAliasSet = new HashMap();

//		G.v().out.println("Checking for Locals " + useLocals + " in these statements: " + useStmts);

		doAnalysis();

		// If any redefinition reaches any use statement, return false
		Iterator useIt = useStmts.iterator();
		while(useIt.hasNext())
		{
			Unit u = useIt.next();
			FlowSet fs = (FlowSet) getFlowBefore(u);
			Iterator redefIt = redefStmts.iterator();
			while(redefIt.hasNext())
			{
				if(fs.contains(redefIt.next()))
				{
//					G.v().out.print("LIF = false ");
					return false;
				}
			}
			List aliases = null;
			Iterator fsIt = fs.iterator();
			while(fsIt.hasNext())
			{
				Object o = fsIt.next();
				if( o instanceof List )
					aliases = (List) o;
			}
			if( aliases != null && !aliases.contains(new EquivalentValue(stmtToLocal.get(u))) )
			{
//				G.v().out.print("LIF = false ");
				return false;
			}
		}
//		G.v().out.print("LIF = true ");
		return true;
	}
	
	public Map getFirstUseToAliasSet()
	{
		return firstUseToAliasSet;
	}

	protected void merge(Object in1, Object in2, Object out)
	{
		FlowSet inSet1 = (FlowSet) in1;
		FlowSet inSet2 = (FlowSet) in2;
		FlowSet outSet = (FlowSet) out;
		
		
		inSet1.union(inSet2, outSet);
		List aliases1 = null;
		List aliases2 = null;
		Iterator outIt = outSet.iterator();
		while(outIt.hasNext())
		{
			Object o = outIt.next();
			if( o instanceof List )
			{
				if(aliases1 == null)
					aliases1 = (List) o;
				else
					aliases2 = (List) o;
			}
		}
		if(aliases1 != null && aliases2 != null)
		{
			outSet.remove(aliases2);
			Iterator aliasIt = aliases1.iterator();
			while(aliasIt.hasNext())
			{
				Object o = aliasIt.next();
				if(!aliases2.contains(o))
					aliasIt.remove();
			}
		}
	}
	
	protected void flowThrough(Object inValue, Object unit,
			Object outValue)
	{
		FlowSet in  = (FlowSet) inValue;
		FlowSet out = (FlowSet) outValue;
		Stmt stmt = (Stmt) unit;
		
		in.copy(out);

		// get list of definitions at this unit
		List newDefs = new ArrayList();
		Iterator newDefBoxesIt = stmt.getDefBoxes().iterator();
		while(newDefBoxesIt.hasNext())
		{
			newDefs.add( ((ValueBox) newDefBoxesIt.next()).getValue() );
		}
		
		// check if any locals of interest were redefined here
		Iterator useLocalsIt = useLocals.iterator();
		while(useLocalsIt.hasNext())
		{
			Local useLocal = useLocalsIt.next();
			if( newDefs.contains(useLocal) ) // if a relevant local was (re)def'd here
			{
				Iterator outIt = out.iterator();
				while(outIt.hasNext())
				{
					Object o = outIt.next();
					if( o instanceof Stmt )
					{
						Stmt s = (Stmt) o;
						if(stmtToLocal.get(s) == useLocal) // if a use of this local exists in the flow set
							redefStmts.add(stmt); // mark this as an active redef stmt
					}
				}
			}
		}

		// if this is a redefinition statement, flow it forwards
		if( redefStmts.contains(stmt) )
		{
			out.add(stmt);
		}
		
		// if this is a boundary statement, clear everything but aliases from the flow set
		if( boundaryStmts.contains(stmt) )
		{
			// find the alias entry in the flow set
/*			List aliases = null;
			Iterator outIt = out.iterator();
			while(outIt.hasNext())
			{
				Object o = outIt.next();
				if( o instanceof List )
					aliases = (List) o;
			}
*/			
			// clear the flow set, and add aliases back in
			out.clear();
//			if(aliases != null)
//				out.add(aliases);
		}
		
		// if this is a use statement (of interest), flow it forward
		// if it's the first use statement, get an alias list
		if( useStmts.contains(stmt) )
		{
			if(out.size() == 0)
			{
				// Add a list of aliases to the used value
				Local l = stmtToLocal.get(stmt);
				List aliasList = el.getCopiesOfAt(l, stmt);
				if(aliasList.size() == 0)
					aliasList.add(l); // covers the case of this or a parameter, where getCopiesOfAt doesn't seem to work right now
				List newAliasList = new ArrayList();
				newAliasList.addAll(aliasList);
				firstUseToAliasSet.put(stmt, newAliasList);
//				G.v().out.println("Aliases of " + l + " at " + stmt + " are " + aliasList);
				out.add(aliasList);
			}
			out.add(stmt);
		}
		
		// update the alias list if this is a definition statement
		if( stmt instanceof DefinitionStmt )
		{
			List aliases = null;
			Iterator outIt = out.iterator();
			while(outIt.hasNext())
			{
				Object o = outIt.next();
				if( o instanceof List )
					aliases = (List) o;
			}
			if( aliases != null )
			{
				if( aliases.contains( new EquivalentValue(((DefinitionStmt)stmt).getRightOp()) ) )
				{
					Iterator newDefsIt = newDefs.iterator();
					while(newDefsIt.hasNext())
						aliases.add( new EquivalentValue( (Value) newDefsIt.next() ) );
				}
				else
				{
					Iterator newDefsIt = newDefs.iterator();
					while(newDefsIt.hasNext())
						aliases.remove( new EquivalentValue( (Value) newDefsIt.next() ) );
				}
			}
		}
			
	}
	
	protected void copy(Object source, Object dest)
	{
		
		FlowSet sourceSet = (FlowSet) source;
		FlowSet destSet   = (FlowSet) dest;
		
		sourceSet.copy(destSet);
		
	}
	
	protected Object entryInitialFlow()
	{
		return new ArraySparseSet();
	}
	
	protected Object newInitialFlow()
	{
		return new ArraySparseSet();
	}	
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy