306 lines
6.4 KiB
Java
306 lines
6.4 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.Collection;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.LinkedList;
|
|
import java.util.Set;
|
|
|
|
import com.ibm.wala.classLoader.CallSiteReference;
|
|
import com.ibm.wala.classLoader.IMethod;
|
|
import com.ibm.wala.ipa.callgraph.CGNode;
|
|
import com.ibm.wala.ipa.callgraph.CallGraph;
|
|
import com.ibm.wala.ipa.callgraph.Context;
|
|
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
|
import com.ibm.wala.types.MethodReference;
|
|
import com.ibm.wala.util.intset.BitVectorIntSet;
|
|
import com.ibm.wala.util.intset.IntSet;
|
|
|
|
public class PrunedCallGraph implements CallGraph {
|
|
|
|
private CallGraph cg;
|
|
private Set<CGNode> keep;
|
|
|
|
public PrunedCallGraph(CallGraph cg, Set<CGNode> keep) {
|
|
this.cg = cg;
|
|
this.keep = keep;
|
|
}
|
|
|
|
public void removeNodeAndEdges(CGNode n) throws UnsupportedOperationException {
|
|
cg.removeNodeAndEdges(n);
|
|
keep.remove(n);
|
|
}
|
|
|
|
public Iterator<CGNode> iterator() {
|
|
Iterator<CGNode> tmp = cg.iterator();
|
|
Collection<CGNode> col = new LinkedList<CGNode>();
|
|
while (tmp.hasNext()) {
|
|
CGNode n = tmp.next();
|
|
if (keep.contains(n)) {
|
|
col.add(n);
|
|
}
|
|
}
|
|
|
|
return col.iterator();
|
|
}
|
|
|
|
public int getNumberOfNodes() {
|
|
return keep.size();
|
|
}
|
|
|
|
public void addNode(CGNode n) {
|
|
cg.addNode(n);
|
|
keep.add(n);
|
|
}
|
|
|
|
public void removeNode(CGNode n) throws UnsupportedOperationException {
|
|
cg.removeNode(n);
|
|
keep.remove(n);
|
|
}
|
|
|
|
public boolean containsNode(CGNode n) {
|
|
return cg.containsNode(n) && keep.contains(n);
|
|
}
|
|
|
|
public Iterator<CGNode> getPredNodes(CGNode n) {
|
|
Iterator<CGNode> tmp = cg.getPredNodes(n);
|
|
Collection<CGNode> col = new LinkedList<CGNode>();
|
|
while (tmp.hasNext()) {
|
|
CGNode no = tmp.next();
|
|
if (keep.contains(no)) {
|
|
col.add(no);
|
|
}
|
|
}
|
|
|
|
return col.iterator();
|
|
}
|
|
|
|
public int getPredNodeCount(CGNode n) {
|
|
Iterator<CGNode> tmp = cg.getPredNodes(n);
|
|
int cnt = 0;
|
|
while (tmp.hasNext()) {
|
|
CGNode no = tmp.next();
|
|
if (keep.contains(no)) {
|
|
cnt++;
|
|
}
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
|
|
public Iterator<CGNode> getSuccNodes(CGNode n) {
|
|
Iterator<CGNode> tmp = cg.getSuccNodes(n);
|
|
Collection<CGNode> col = new LinkedList<CGNode>();
|
|
while (tmp.hasNext()) {
|
|
CGNode no = tmp.next();
|
|
if (keep.contains(no)) {
|
|
col.add(no);
|
|
}
|
|
}
|
|
|
|
return col.iterator();
|
|
}
|
|
|
|
|
|
public int getSuccNodeCount(CGNode n) {
|
|
Iterator<CGNode> tmp = cg.getSuccNodes(n);
|
|
int cnt = 0;
|
|
while (tmp.hasNext()) {
|
|
CGNode no = tmp.next();
|
|
if (keep.contains(no)) {
|
|
cnt++;
|
|
}
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
|
|
public void addEdge(CGNode src, CGNode dst) {
|
|
if (keep.contains(src) && keep.contains(dst)){
|
|
cg.addEdge(src, dst);
|
|
}
|
|
}
|
|
|
|
|
|
public void removeEdge(CGNode src, CGNode dst) throws UnsupportedOperationException {
|
|
cg.removeEdge(src, dst);
|
|
}
|
|
|
|
|
|
public void removeAllIncidentEdges(CGNode node) throws UnsupportedOperationException {
|
|
cg.removeAllIncidentEdges(node);
|
|
}
|
|
|
|
|
|
public void removeIncomingEdges(CGNode node) throws UnsupportedOperationException {
|
|
cg.removeIncomingEdges(node);
|
|
}
|
|
|
|
|
|
public void removeOutgoingEdges(CGNode node) throws UnsupportedOperationException {
|
|
cg.removeOutgoingEdges(node);
|
|
}
|
|
|
|
|
|
public boolean hasEdge(CGNode src, CGNode dst) {
|
|
return cg.hasEdge(src, dst) && keep.contains(src) && keep.contains(dst);
|
|
}
|
|
|
|
|
|
public int getNumber(CGNode N) {
|
|
if (keep.contains(N)) {
|
|
return cg.getNumber(N);
|
|
} else {
|
|
return -1;
|
|
}
|
|
|
|
}
|
|
|
|
|
|
public CGNode getNode(int number) {
|
|
if(keep.contains(cg.getNode(number))) {
|
|
return cg.getNode(number);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
public int getMaxNumber() {
|
|
return cg.getMaxNumber();
|
|
}
|
|
|
|
|
|
public Iterator<CGNode> iterateNodes(IntSet s) {
|
|
Iterator<CGNode> tmp = cg.iterateNodes(s);
|
|
Collection<CGNode> col = new LinkedList<CGNode>();
|
|
while (tmp.hasNext()) {
|
|
CGNode n = tmp.next();
|
|
if (keep.contains(n)) {
|
|
col.add(n);
|
|
}
|
|
}
|
|
|
|
return col.iterator();
|
|
}
|
|
|
|
|
|
public IntSet getSuccNodeNumbers(CGNode node) {
|
|
if (!keep.contains(node)){
|
|
return null;
|
|
}
|
|
IntSet tmp = cg.getSuccNodeNumbers(node);
|
|
BitVectorIntSet kp = new BitVectorIntSet();
|
|
for (CGNode n : keep) {
|
|
kp.add(getNumber(n));
|
|
}
|
|
return tmp.intersection(kp);
|
|
}
|
|
|
|
|
|
public IntSet getPredNodeNumbers(CGNode node) {
|
|
if (!keep.contains(node)){
|
|
return null;
|
|
}
|
|
if (!keep.contains(node)){
|
|
return null;
|
|
}
|
|
IntSet tmp = cg.getPredNodeNumbers(node);
|
|
BitVectorIntSet kp = new BitVectorIntSet();
|
|
for (CGNode n : keep) {
|
|
kp.add(getNumber(n));
|
|
}
|
|
return tmp.intersection(kp);
|
|
}
|
|
|
|
|
|
public CGNode getFakeRootNode() {
|
|
if (keep.contains(cg.getFakeRootNode())) {
|
|
return cg.getFakeRootNode();
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
public Collection<CGNode> getEntrypointNodes() {
|
|
Collection<CGNode> tmp = cg.getEntrypointNodes();
|
|
Set<CGNode> ret = new HashSet<CGNode>();
|
|
for (CGNode n : tmp) {
|
|
if (keep.contains(n)) {
|
|
ret.add(n);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
public CGNode getNode(IMethod method, Context C) {
|
|
if(keep.contains(cg.getNode(method, C))) {
|
|
return cg.getNode(method, C);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
|
|
public Set<CGNode> getNodes(MethodReference m) {
|
|
Set<CGNode> tmp = cg.getNodes(m);
|
|
Set<CGNode> ret = new HashSet<CGNode>();
|
|
for (CGNode n : tmp) {
|
|
if (keep.contains(n)) {
|
|
ret.add(n);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
public IClassHierarchy getClassHierarchy() {
|
|
return cg.getClassHierarchy();
|
|
}
|
|
|
|
|
|
public Set<CGNode> getPossibleTargets(CGNode node, CallSiteReference site) {
|
|
if (!keep.contains(node)){
|
|
return null;
|
|
}
|
|
Set<CGNode> tmp = cg.getPossibleTargets(node, site);
|
|
Set<CGNode> ret = new HashSet<CGNode>();
|
|
for (CGNode n : tmp) {
|
|
if (keep.contains(n)) {
|
|
ret.add(n);
|
|
}
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
public int getNumberOfTargets(CGNode node, CallSiteReference site) {
|
|
if (!keep.contains(node)){
|
|
return -1;
|
|
}
|
|
return getPossibleTargets(node, site).size();
|
|
}
|
|
|
|
|
|
public Iterator<CallSiteReference> getPossibleSites(CGNode src, CGNode target) {
|
|
if (!(keep.contains(src) && keep.contains(target))){
|
|
return null;
|
|
}
|
|
return cg.getPossibleSites(src, target);
|
|
}
|
|
|
|
}
|