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

soot.jimple.toolkits.annotation.purity.DirectedCallGraph Maven / Gradle / Ivy

There is a newer version: 1.12.0
Show newest version
/* Soot - a J*va Optimization Framework
 * Copyright (C) 2005 Antoine Mine
 *
 * 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.
 */

/**
 * Implementation of the paper "A Combined Pointer and Purity Analysis for
 * Java Programs" by Alexandru Salcianu and Martin Rinard, within the
 * Soot Optimization Framework.
 *
 * by Antoine Mine, 2005/01/24
 */

package soot.jimple.toolkits.annotation.purity;
import java.util.*;
import soot.*;
import soot.util.*;
import soot.jimple.toolkits.callgraph.*;
import soot.toolkits.graph.*;

/**
 * Builds a DirectedGraph from a CallGraph and SootMethodFilter.
 *
 * This is used in AbstractInterproceduralAnalysis to construct a reverse
 * pseudo topological order on which to iterate.
 * You can specify a SootMethodFilter to trim the graph by cutting 
 * call edges strarting
 *
 * Methods filtered-out by the SootMethodFilter will not appear in the
 * DirectedGraph!
 */
public class DirectedCallGraph implements DirectedGraph {

    protected Set  nodes;
    protected Map  succ;
    protected Map  pred;
    protected List heads;
    protected List tails;
    protected int  size;

    /**
     * The constructor does all the work here.
     * After constructed, you can safely use all interface methods.
     * Moreover, these methods should perform very fastly...
     *
     * The DirectedGraph will only contain methods in call paths from a method
     * in head and comprising only methods wanted by filter.
     * Moreover, only concrete methods are put in the graph...
     *
     * @param heads is a List of SootMethod
     */
    public DirectedCallGraph(CallGraph        cg,
			     SootMethodFilter filter,
			     Iterator         heads,
			     boolean          verbose)
    {
	// filter heads by filter
	List filteredHeads = new LinkedList();
	while (heads.hasNext()) {
	    SootMethod m = (SootMethod) heads.next();
	    if (m.isConcrete() && filter.want(m)) filteredHeads.add(m);
	}

	this.nodes = new HashSet(filteredHeads);
	
	MultiMap s = new HashMultiMap();
	MultiMap p = new HashMultiMap();

	// simple breadth-first visit
	Set remain = new HashSet(filteredHeads);
	int nb = 0;
	if (verbose) G.v().out.println("[AM] dumping method dependencies");
	while (!remain.isEmpty()) {
	    Set newRemain = new HashSet();
	    Iterator it = remain.iterator();
	    while (it.hasNext()) {
		SootMethod m = (SootMethod)it.next();
		Iterator itt = cg.edgesOutOf(m);
		if (verbose) 
		    G.v().out.println(" |- "+m.toString()+" calls");
		while (itt.hasNext())  {
		    Edge edge = (Edge)itt.next();
		    SootMethod mm = edge.tgt();
		    boolean keep = mm.isConcrete() && filter.want(mm);
		    if (verbose)
			G.v().out.println(" |  |- "+mm.toString()+
					  (keep?"":" (filtered out)"));
		    if (keep) {
			if (this.nodes.add(mm)) newRemain.add(mm);
			s.put(m,mm);
			p.put(mm,m);
		    }
		}
		nb++;
	    }
	    remain = newRemain;
	}
	G.v().out.println("[AM] number of methods to be analysed: "+nb);

	// MultiMap -> Map of List
	this.succ   = new HashMap();
	this.pred   = new HashMap();
	this.tails  = new LinkedList();
	this.heads  = new LinkedList();
	Iterator it = this.nodes.iterator();
	while (it.hasNext()) {
	    Object x = it.next();
	    Set ss   = s.get(x);
	    Set pp   = p.get(x);
	    this.succ.put(x, new LinkedList(ss));
	    this.pred.put(x, new LinkedList(pp));
	    if (ss.isEmpty()) this.tails.add(x);
	    if (pp.isEmpty()) this.heads.add(x);
	}

	this.size  = this.nodes.size();
    }

    /** You get a List of SootMethod. */
    public List getHeads() { return heads; }

    /** You get a List of SootMethod. */
    public List getTails() { return tails; }

    /** You get an Iterator on SootMethod. */
    public Iterator iterator() { return nodes.iterator(); }

    public int size() { return size; }
    
    /** You get a List of SootMethod. */
    public List getSuccsOf(Object s) { return succ.get(s); }

    /** You get a List of SootMethod. */
    public List getPredsOf(Object s) { return pred.get(s); }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy