137 lines
3.8 KiB
Java
137 lines
3.8 KiB
Java
/******************************************************************************
|
|
* Copyright (c) 2002 - 2014 IBM Corporation.
|
|
* All rights reserved. This program and the accompanying materials
|
|
* are made available under the terms of the Eclipse Public License v1.0
|
|
* which accompanies this distribution, and is available at
|
|
* http://www.eclipse.org/legal/epl-v10.html
|
|
*
|
|
* Contributors:
|
|
* IBM Corporation - initial API and implementation
|
|
*****************************************************************************/
|
|
|
|
package com.ibm.wala.ipa.callgraph.pruned;
|
|
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.LinkedList;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
|
|
import com.ibm.wala.ipa.callgraph.CGNode;
|
|
import com.ibm.wala.ipa.callgraph.CallGraph;
|
|
|
|
|
|
public final class CallGraphPruning {
|
|
|
|
public CallGraphPruning(CallGraph cg) {
|
|
this.cg = cg;
|
|
}
|
|
|
|
private PruningPolicy pruningPolicy;
|
|
private Set<CGNode> keep;
|
|
private LinkedList<CGNode> visited;
|
|
private List<CGNode> marked;
|
|
private int depth;
|
|
private CallGraph cg;
|
|
|
|
private boolean DEBUG = false;
|
|
|
|
/**
|
|
* Searches all nodes in the callgraph that correspond to a method of the application (and not the system library).
|
|
* It includes methods from the system library that transitively may call back into the application.
|
|
* @return Set of relevant callgraph nodes.
|
|
*/
|
|
public Set<CGNode> findApplicationNodes() {
|
|
return findApplicationNodes(0);
|
|
}
|
|
|
|
/**
|
|
* Searches all nodes in the callgraph that correspond to a method of the application (and not the system library).
|
|
* It includes methods from the system library that transitively may call back into the application. Library
|
|
* methods that do not transitively call back into application methods are cut at the level provided by parameter
|
|
* depth.
|
|
* @param depth The level at which non-returning library methods are cut off.
|
|
* @return Set of relevant callgraph nodes.
|
|
*/
|
|
public Set<CGNode> findApplicationNodes(final int depth) {
|
|
return findNodes(depth, ApplicationLoaderPolicy.INSTANCE);
|
|
}
|
|
|
|
/**
|
|
* Searches all nodes in the callgraph according to the given pruning policy. It includes all methods which
|
|
* transitively may call methods which comply to the given pruning policy. All other methods are cut at the level
|
|
* provided by parameter 'depth'
|
|
* @param depth the level at which methods which do not comply to the given pruning policy are cut off.
|
|
* @param policy pruning policy which decides which branches are kept in the call graph
|
|
* @return set of relevant callgraph nodes
|
|
*/
|
|
public Set<CGNode> findNodes(final int depth, PruningPolicy policy) {
|
|
if (DEBUG) {
|
|
System.out.println("Running optimization with depth: " + depth);
|
|
}
|
|
|
|
this.marked = new LinkedList<CGNode>();
|
|
this.keep = new HashSet<CGNode>();
|
|
this.visited = new LinkedList<CGNode>();
|
|
this.depth = depth;
|
|
this.pruningPolicy = policy;
|
|
|
|
dfs(cg.getFakeRootNode());
|
|
|
|
return keep;
|
|
}
|
|
|
|
private void dfs(CGNode root) {
|
|
|
|
visited.addLast(root);
|
|
|
|
Iterator<CGNode> it = cg.getSuccNodes(root);
|
|
while (it.hasNext()) {
|
|
CGNode next = it.next();
|
|
if (!marked.contains(next)) {
|
|
marked.add(next);
|
|
dfs(next);
|
|
} else {
|
|
if (keep.contains(next)) {
|
|
keep.addAll(visited);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pruningPolicy.check(root)) {
|
|
keep.addAll(visited);
|
|
addDepth(root);
|
|
}
|
|
visited.removeLast();
|
|
}
|
|
|
|
private void addDepth(CGNode node) {
|
|
|
|
LinkedList<CGNode> A = new LinkedList<CGNode>();
|
|
LinkedList<CGNode> B = new LinkedList<CGNode>();
|
|
int i = depth;
|
|
A.add(node);
|
|
while (i > 0) {
|
|
|
|
for (CGNode n : A) {
|
|
Iterator<CGNode> it = cg.getSuccNodes(n);
|
|
while (it.hasNext()) {
|
|
B.add(it.next());
|
|
}
|
|
}
|
|
|
|
if (DEBUG) {
|
|
System.out.println("Tiefe: " + B);
|
|
}
|
|
|
|
keep.addAll(B);
|
|
A.clear();
|
|
A.addAll(B);
|
|
B.clear();
|
|
i--;
|
|
}
|
|
}
|
|
|
|
|
|
}
|