restructure to allow CGNodes to dwell in more than one CallGraph. lift some functions up from CGNode to CallGraph

git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@1422 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
sjfink 2007-07-11 16:24:58 +00:00
parent d72e0a1752
commit fd1a1d4cae
16 changed files with 189 additions and 151 deletions

View File

@ -65,7 +65,7 @@ public class EMFBridge {
for (Iterator it2 = n.iterateSites(); it2.hasNext();) { for (Iterator it2 = n.iterateSites(); it2.hasNext();) {
CallSiteReference site = (CallSiteReference) it2.next(); CallSiteReference site = (CallSiteReference) it2.next();
ECallSite eSite = makeCallSite(method, site); ECallSite eSite = makeCallSite(method, site);
for (Iterator it3 = n.getPossibleTargets(site).iterator(); it3.hasNext();) { for (Iterator it3 = cg.getPossibleTargets(n,site).iterator(); it3.hasNext();) {
CGNode target = (CGNode) it3.next(); CGNode target = (CGNode) it3.next();
result.addEdge(eSite, makeJavaMethod(target.getMethod().getReference())); result.addEdge(eSite, makeJavaMethod(target.getMethod().getReference()));
} }

View File

@ -11,7 +11,6 @@
package com.ibm.wala.ipa.callgraph; package com.ibm.wala.ipa.callgraph;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set;
import com.ibm.wala.cfg.ControlFlowGraph; import com.ibm.wala.cfg.ControlFlowGraph;
import com.ibm.wala.classLoader.CallSiteReference; import com.ibm.wala.classLoader.CallSiteReference;
@ -44,40 +43,44 @@ public interface CGNode extends INodeWithNumber, ContextItem {
*/ */
public Context getContext(); public Context getContext();
/** // /**
* Return the set of CGNodes that represent possible targets // * Return the set of CGNodes that represent possible targets
* of a particular call site when invoked in this context. // * of a particular call site when invoked in this context.
*/ // */
Set<CGNode> getPossibleTargets(CallSiteReference site); // Set<CGNode> getPossibleTargets(CallSiteReference site);
/** /**
* @return Iterator of CallSiteReference * @return Iterator of CallSiteReference
*/ */
Iterator<CallSiteReference> iterateSites(); Iterator<CallSiteReference> iterateSites();
// /**
// * @param target
// * @return iterator of CallSiteReference, the call sites in this node that might
// * dispatch to the target node.
// */
// Iterator<CallSiteReference> getPossibleSites(CGNode target);
//
/** /**
* @param target * This is for use only by call graph builders ... not by the general
* @return iterator of CallSiteReference, the call sites in this node that might * public. Clients should not use this.
* dispatch to the target node. *
*/
Iterator<CallSiteReference> getPossibleSites(CGNode target);
/**
* Record that a particular call site might resolve to a call to a * Record that a particular call site might resolve to a call to a
* particular target node. Returns true if this is a new target * particular target node. Returns true if this is a new target
*/ */
@Deprecated
public boolean addTarget(CallSiteReference site, CGNode target); public boolean addTarget(CallSiteReference site, CGNode target);
/** // /**
* @return the number of nodes that the call site current may resolve // * @return the number of nodes that the call site current may resolve
* to // * to
*/ // */
public int getNumberOfTargets(CallSiteReference site); // public int getNumberOfTargets(CallSiteReference site);
/** // /**
* @return the call graph in which this node dwells // * @return the call graph in which this node dwells
*/ // */
public CallGraph getCallGraph(); // public CallGraph getCallGraph();
/** /**
* @return the "default" IR for this node used by the governing call graph * @return the "default" IR for this node used by the governing call graph

View File

@ -11,8 +11,10 @@
package com.ibm.wala.ipa.callgraph; package com.ibm.wala.ipa.callgraph;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator;
import java.util.Set; import java.util.Set;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.cha.IClassHierarchy; import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.types.MethodReference; import com.ibm.wala.types.MethodReference;
@ -21,15 +23,15 @@ import com.ibm.wala.util.graph.NumberedGraph;
/** /**
* Basic interface for a call graph, which is a graph of CGNode * Basic interface for a call graph, which is a graph of CGNode
* *
* *
* @author Stephen Fink * @author Stephen Fink
*/ */
public interface CallGraph extends NumberedGraph<CGNode> { public interface CallGraph extends NumberedGraph<CGNode> {
/** /**
* Return the (fake) interprocedural {@link CGNode root node} * Return the (fake) interprocedural {@link CGNode root node} of the call
* of the call graph. * graph.
* *
* @return the "fake" root node the call graph * @return the "fake" root node the call graph
*/ */
public CGNode getFakeRootNode(); public CGNode getFakeRootNode();
@ -40,29 +42,40 @@ public interface CallGraph extends NumberedGraph<CGNode> {
public Collection<CGNode> getEntrypointNodes(); public Collection<CGNode> getEntrypointNodes();
/** /**
* If you want to get <em> all </em> the nodes corresponding to * If you want to get <em> all </em> the nodes corresponding to a particular
* a particular method, regardless of context, then use * method, regardless of context, then use {@link CGNode getNodes}
* {@link CGNode getNodes}
* *
* @return the node corresponding a method in a context * @return the node corresponding a method in a context
*/ */
public CGNode getNode(IMethod method, Context C); public CGNode getNode(IMethod method, Context C);
/** /**
* @param m a method reference * @param m
* @return the set of all nodes in the call graph that represent * a method reference
* this method. * @return the set of all nodes in the call graph that represent this method.
*/ */
public Set<CGNode> getNodes(MethodReference m); public Set<CGNode> getNodes(MethodReference m);
/**
* Dump the callgraph to the specified file in dotty(1) format.
*/
public void dump(String filename);
/** /**
* @return the governing class hierarchy for this call graph * @return the governing class hierarchy for this call graph
*/ */
public IClassHierarchy getClassHierarchy(); public IClassHierarchy getClassHierarchy();
/**
* Return the set of CGNodes that represent possible targets of a particular
* call site from a particular node
*/
public Set<CGNode> getPossibleTargets(CGNode node, CallSiteReference site);
/**
* @return the number of nodes that the call site may dispatch to
*/
public int getNumberOfTargets(CGNode node, CallSiteReference site);
/**
* @return iterator of CallSiteReference, the call sites in a node that might
* dispatch to the target node.
*/
Iterator<CallSiteReference> getPossibleSites(CGNode src, CGNode target);
} }

View File

@ -10,10 +10,6 @@
*******************************************************************************/ *******************************************************************************/
package com.ibm.wala.ipa.callgraph.impl; package com.ibm.wala.ipa.callgraph.impl;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
@ -94,9 +90,7 @@ public abstract class BasicCallGraph extends AbstractNumberedGraph<CGNode> imple
super(); super();
} }
/** @SuppressWarnings("deprecation")
*
*/
public void init() { public void init() {
fakeRoot = makeFakeRootNode(); fakeRoot = makeFakeRootNode();
Key k = new Key(fakeRoot.getMethod(), fakeRoot.getContext()); Key k = new Key(fakeRoot.getMethod(), fakeRoot.getContext());
@ -197,8 +191,6 @@ public abstract class BasicCallGraph extends AbstractNumberedGraph<CGNode> imple
return method; return method;
} }
public abstract Set<CGNode> getPossibleTargets(CallSiteReference site);
/** /**
* @see java.lang.Object#equals(Object) * @see java.lang.Object#equals(Object)
*/ */
@ -236,7 +228,7 @@ public abstract class BasicCallGraph extends AbstractNumberedGraph<CGNode> imple
if (n.getMethod() != null) { if (n.getMethod() != null) {
for (Iterator sites = n.iterateSites(); sites.hasNext();) { for (Iterator sites = n.iterateSites(); sites.hasNext();) {
CallSiteReference site = (CallSiteReference) sites.next(); CallSiteReference site = (CallSiteReference) sites.next();
Iterator targets = n.getPossibleTargets(site).iterator(); Iterator targets = getPossibleTargets(n, site).iterator();
if (targets.hasNext()) { if (targets.hasNext()) {
result.append(" - " + site + "\n"); result.append(" - " + site + "\n");
} }
@ -250,38 +242,6 @@ public abstract class BasicCallGraph extends AbstractNumberedGraph<CGNode> imple
return result.toString(); return result.toString();
} }
/**
* Dump this callgraph to the specified file in dotty(1) format.
* @throws IllegalArgumentException if filename is null
*/
public void dump(String filename) {
if (filename == null) {
throw new IllegalArgumentException("filename is null");
}
File file = new File(filename);
try {
PrintWriter out = new PrintWriter(new FileOutputStream(file));
out.println("digraph callgraph {");
for (Iterator it = iterator(); it.hasNext();) {
CGNode n = (CGNode) it.next();
for (Iterator it2 = getSuccNodes(n); it2.hasNext();) {
CGNode m = (CGNode) it2.next();
out.println(" \"" + prettyPrint(n) + "\" -> \"" + prettyPrint(m) + "\"");
}
}
out.println("}");
out.close();
} catch (IOException e) {
e.printStackTrace();
Assertions.UNREACHABLE();
}
}
private String prettyPrint(CGNode n) {
String s = n.toString().replace(",", "\\n");
return s.replace(" > Context: ", "\\n");
}
@Override @Override
public void removeNodeAndEdges(CGNode N) { public void removeNodeAndEdges(CGNode N) {
Assertions.UNREACHABLE(); Assertions.UNREACHABLE();

View File

@ -146,8 +146,7 @@ public class ExplicitCallGraph extends BasicCallGraph implements BytecodeConstan
super(method, C); super(method, C);
} }
@Override protected Set<CGNode> getPossibleTargets(CallSiteReference site) {
public Set<CGNode> getPossibleTargets(CallSiteReference site) {
Object result = targets.get(site.getProgramCounter()); Object result = targets.get(site.getProgramCounter());
if (result == null) { if (result == null) {
@ -165,7 +164,7 @@ public class ExplicitCallGraph extends BasicCallGraph implements BytecodeConstan
} }
} }
public IntSet getPossibleTargetNumbers(CallSiteReference site) { protected IntSet getPossibleTargetNumbers(CallSiteReference site) {
Object t = targets.get(site.getProgramCounter()); Object t = targets.get(site.getProgramCounter());
if (t == null) { if (t == null) {
@ -180,7 +179,7 @@ public class ExplicitCallGraph extends BasicCallGraph implements BytecodeConstan
/* /*
* @see com.ibm.wala.ipa.callgraph.CGNode#getPossibleSites(com.ibm.wala.ipa.callgraph.CGNode) * @see com.ibm.wala.ipa.callgraph.CGNode#getPossibleSites(com.ibm.wala.ipa.callgraph.CGNode)
*/ */
public Iterator<CallSiteReference> getPossibleSites(final CGNode to) { protected Iterator<CallSiteReference> getPossibleSites(final CGNode to) {
final int n = getCallGraph().getNumber(to); final int n = getCallGraph().getNumber(to);
return new FilterIterator<CallSiteReference>(iterateSites(), new Filter() { return new FilterIterator<CallSiteReference>(iterateSites(), new Filter() {
public boolean accepts(Object o) { public boolean accepts(Object o) {
@ -189,6 +188,19 @@ public class ExplicitCallGraph extends BasicCallGraph implements BytecodeConstan
} }
}); });
} }
protected int getNumberOfTargets(CallSiteReference site) {
Object result = targets.get(site.getProgramCounter());
if (result == null) {
return 0;
} else if (result instanceof CGNode) {
return 1;
} else {
return ((IntSet) result).size();
}
}
@Override @Override
public boolean addTarget(CallSiteReference site, CGNode tNode) { public boolean addTarget(CallSiteReference site, CGNode tNode) {
@ -229,20 +241,6 @@ public class ExplicitCallGraph extends BasicCallGraph implements BytecodeConstan
} }
} }
/*
* @see com.ibm.detox.ipa.callgraph.CGNode#getNumberOfTargets(com.ibm.wala.classLoader.CallSiteReference)
*/
public int getNumberOfTargets(CallSiteReference site) {
Object result = targets.get(site.getProgramCounter());
if (result == null) {
return 0;
} else if (result instanceof CGNode) {
return 1;
} else {
return ((IntSet) result).size();
}
}
/* /*
* @see com.ibm.wala.ipa.callgraph.CGNode#iterateSites() * @see com.ibm.wala.ipa.callgraph.CGNode#iterateSites()
@ -295,7 +293,7 @@ public class ExplicitCallGraph extends BasicCallGraph implements BytecodeConstan
return getMethod().hashCode() * 8681 + getContext().hashCode(); return getMethod().hashCode() * 8681 + getContext().hashCode();
} }
public MutableSharedBitVectorIntSet getAllTargetNumbers() { protected MutableSharedBitVectorIntSet getAllTargetNumbers() {
return allTargets; return allTargets;
} }
@ -441,4 +439,43 @@ public class ExplicitCallGraph extends BasicCallGraph implements BytecodeConstan
protected ExplicitEdgeManager makeEdgeManger() { protected ExplicitEdgeManager makeEdgeManger() {
return new ExplicitEdgeManager(); return new ExplicitEdgeManager();
} }
public int getNumberOfTargets(CGNode node, CallSiteReference site) {
if (!containsNode(node)) {
throw new IllegalArgumentException("node not in callgraph " + node);
}
assert (node instanceof ExplicitNode);
ExplicitNode n = (ExplicitNode)node;
return n.getNumberOfTargets(site);
}
public Iterator<CallSiteReference> getPossibleSites(CGNode src, CGNode target) {
if (!containsNode(src)) {
throw new IllegalArgumentException("node not in callgraph " + src);
}
if (!containsNode(target)) {
throw new IllegalArgumentException("node not in callgraph " + target);
}
assert (src instanceof ExplicitNode);
ExplicitNode n = (ExplicitNode)src;
return n.getPossibleSites(target);
}
public Set<CGNode> getPossibleTargets(CGNode node, CallSiteReference site) {
if (!containsNode(node)) {
throw new IllegalArgumentException("node not in callgraph " + node);
}
assert (node instanceof ExplicitNode);
ExplicitNode n = (ExplicitNode)node;
return n.getPossibleTargets(site);
}
public IntSet getPossibleTargetNumbers(CGNode node, CallSiteReference site) {
if (!containsNode(node)) {
throw new IllegalArgumentException("node not in callgraph " + node);
}
assert (node instanceof ExplicitNode);
ExplicitNode n = (ExplicitNode)node;
return n.getPossibleTargetNumbers(site);
}
} }

View File

@ -4,6 +4,7 @@ import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.Set; import java.util.Set;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IMethod; import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph; import com.ibm.wala.ipa.callgraph.CallGraph;
@ -125,4 +126,19 @@ public class PartialCallGraph extends DelegatingGraph<CGNode> implements CallGra
return x; return x;
} }
public int getNumberOfTargets(CGNode node, CallSiteReference site) {
Assertions.UNREACHABLE("TODO");
return 0;
}
public Iterator<CallSiteReference> getPossibleSites(CGNode src, CGNode target) {
Assertions.UNREACHABLE("TODO");
return null;
}
public Set<CGNode> getPossibleTargets(CGNode node, CallSiteReference site) {
Assertions.UNREACHABLE("TODO");
return null;
}
} }

View File

@ -424,14 +424,12 @@ public class PointerAnalysisImpl extends AbstractPointerAnalysis {
} }
/** /**
* @param node
* @param call
* @return the points-to set for the exceptional return values from a * @return the points-to set for the exceptional return values from a
* particular call site * particular call site
*/ */
private OrdinalSet<InstanceKey> computeImplicitExceptionsForCall(CGNode node, SSAInvokeInstruction call) { private OrdinalSet<InstanceKey> computeImplicitExceptionsForCall(CGNode node, SSAInvokeInstruction call) {
MutableSparseIntSet S = new MutableSparseIntSet(); MutableSparseIntSet S = new MutableSparseIntSet();
for (Iterator it = node.getPossibleTargets(call.getCallSite()).iterator(); it.hasNext();) { for (Iterator it = getCallGraph().getPossibleTargets(node, call.getCallSite()).iterator(); it.hasNext();) {
CGNode target = (CGNode) it.next(); CGNode target = (CGNode) it.next();
PointerKey retVal = pointerKeys.getPointerKeyForExceptionalReturnValue(target); PointerKey retVal = pointerKeys.getPointerKeyForExceptionalReturnValue(target);
IntSet set = getPointsToSet(retVal).getBackingSet(); IntSet set = getPointsToSet(retVal).getBackingSet();

View File

@ -461,7 +461,7 @@ public class PointerFlowGraph extends AbstractGraph<PointerKey> {
@Override @Override
public void visitInvoke(SSAInvokeInstruction instruction) { public void visitInvoke(SSAInvokeInstruction instruction) {
for (Iterator it = node.getPossibleTargets(instruction.getCallSite()).iterator(); it.hasNext();) { for (Iterator it = cg.getPossibleTargets(node, instruction.getCallSite()).iterator(); it.hasNext();) {
CGNode target = (CGNode) it.next(); CGNode target = (CGNode) it.next();
// some methods, like unmodelled natives, do not have IR. // some methods, like unmodelled natives, do not have IR.

View File

@ -1418,6 +1418,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
* if non-null, then this is the unique PointerKey that catches all * if non-null, then this is the unique PointerKey that catches all
* exceptions from this call site. * exceptions from this call site.
*/ */
@SuppressWarnings("deprecation")
private void processResolvedCall(CGNode caller, SSAAbstractInvokeInstruction instruction, CGNode target, private void processResolvedCall(CGNode caller, SSAAbstractInvokeInstruction instruction, CGNode target,
InstanceKey[][] constParams, PointerKey uniqueCatchKey) { InstanceKey[][] constParams, PointerKey uniqueCatchKey) {
@ -1660,7 +1661,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
Trace.println("Warning: null target for call " + call + " " + iKey); Trace.println("Warning: null target for call " + call + " " + iKey);
} }
} else { } else {
IntSet targets = node.getPossibleTargetNumbers(call.getCallSite()); IntSet targets = getCallGraph().getPossibleTargetNumbers(node,call.getCallSite());
if (targets != null && targets.contains(target.getGraphNodeId())) { if (targets != null && targets.contains(target.getGraphNodeId())) {
// do nothing; we've previously discovered and handled this // do nothing; we've previously discovered and handled this
// receiver for this call site. // receiver for this call site.
@ -1703,7 +1704,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
private boolean willNeverChangeAgain(IntSet receivers) { private boolean willNeverChangeAgain(IntSet receivers) {
int bound = getBoundOnNumberOfTargets(node, call.getSite()); int bound = getBoundOnNumberOfTargets(node, call.getSite());
if (bound > -1) { if (bound > -1) {
int nTargets = node.getNumberOfTargets(call.getSite()); int nTargets = getCallGraph().getNumberOfTargets(node, call.getSite());
if (Assertions.verifyAssertions) { if (Assertions.verifyAssertions) {
if (nTargets > bound) { if (nTargets > bound) {
Trace.println("node: " + node); Trace.println("node: " + node);
@ -1711,7 +1712,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
Trace.println("instruction " + call); Trace.println("instruction " + call);
Trace.println("nTargets: " + nTargets); Trace.println("nTargets: " + nTargets);
Trace.println("bound: " + bound); Trace.println("bound: " + bound);
for (Iterator it = node.getPossibleTargets(call.getSite()).iterator(); it.hasNext();) { for (Iterator it = getCallGraph().getPossibleTargets(node, call.getSite()).iterator(); it.hasNext();) {
Trace.println(" " + it.next()); Trace.println(" " + it.next());
} }
for (IntIterator intIt = receivers.intIterator(); intIt.hasNext();) { for (IntIterator intIt = receivers.intIterator(); intIt.hasNext();) {

View File

@ -323,6 +323,7 @@ public abstract class AbstractRTABuilder extends PropagationCallGraphBuilder {
* *
* Side effect: add edge to the call graph. * Side effect: add edge to the call graph.
*/ */
@SuppressWarnings("deprecation")
void processResolvedCall(CGNode caller, CallSiteReference site, CGNode target) { void processResolvedCall(CGNode caller, CallSiteReference site, CGNode target) {
if (DEBUG) { if (DEBUG) {

View File

@ -188,7 +188,7 @@ public class BasicRTABuilder extends AbstractRTABuilder {
} }
} }
IntSet targets = caller.getPossibleTargetNumbers(site); IntSet targets = getCallGraph().getPossibleTargetNumbers(caller,site);
if (targets != null && targets.contains(target.getGraphNodeId())) { if (targets != null && targets.contains(target.getGraphNodeId())) {
// do nothing; we've previously discovered and handled this // do nothing; we've previously discovered and handled this
// receiver for this call site. // receiver for this call site.

View File

@ -79,7 +79,7 @@ public class DelegatingExplicitCallGraph extends ExplicitCallGraph {
Object n = it.next(); Object n = it.next();
if (n instanceof CallSite) { if (n instanceof CallSite) {
ExplicitNode delegate = (ExplicitNode) ((CallSite) n).getNode(); ExplicitNode delegate = (ExplicitNode) ((CallSite) n).getNode();
IntSet s = delegate.getPossibleTargetNumbers(((CallSite) n).getSite()); IntSet s = DelegatingExplicitCallGraph.this.getPossibleTargetNumbers(delegate, ((CallSite) n).getSite());
if (s != null) { if (s != null) {
result.addAll(s); result.addAll(s);
} }
@ -98,7 +98,7 @@ public class DelegatingExplicitCallGraph extends ExplicitCallGraph {
CallSite p = (CallSite) result; CallSite p = (CallSite) result;
CGNode n = p.getNode(); CGNode n = p.getNode();
CallSiteReference s = p.getSite(); CallSiteReference s = p.getSite();
return n.getPossibleTargets(s); return DelegatingExplicitCallGraph.this.getPossibleTargets(n, s);
} else { } else {
return super.getPossibleTargets(site); return super.getPossibleTargets(site);
} }
@ -125,7 +125,7 @@ public class DelegatingExplicitCallGraph extends ExplicitCallGraph {
Object n = it.next(); Object n = it.next();
if (n instanceof CallSite) { if (n instanceof CallSite) {
ExplicitNode delegate = (ExplicitNode) ((CallSite) n).getNode(); ExplicitNode delegate = (ExplicitNode) ((CallSite) n).getNode();
IntSet s = delegate.getPossibleTargetNumbers(((CallSite) n).getSite()); IntSet s = DelegatingExplicitCallGraph.this.getPossibleTargetNumbers(delegate,((CallSite) n).getSite());
if (s!= null && s.contains(y)) { if (s!= null && s.contains(y)) {
return true; return true;
} }
@ -142,7 +142,7 @@ public class DelegatingExplicitCallGraph extends ExplicitCallGraph {
CallSite p = (CallSite) result; CallSite p = (CallSite) result;
CGNode n = p.getNode(); CGNode n = p.getNode();
CallSiteReference s = p.getSite(); CallSiteReference s = p.getSite();
return n.getNumberOfTargets(s); return DelegatingExplicitCallGraph.this.getNumberOfTargets(n,s);
} else { } else {
return super.getNumberOfTargets(site); return super.getNumberOfTargets(site);
} }

View File

@ -277,7 +277,7 @@ public class InterproceduralCFG implements NumberedGraph<BasicBlockInContext> {
Trace.println("got Site: " + site); Trace.println("got Site: " + site);
} }
boolean irrelevantTargets = false; boolean irrelevantTargets = false;
for (Iterator ts = n.getPossibleTargets(site).iterator(); ts.hasNext();) { for (Iterator ts = cg.getPossibleTargets(n, site).iterator(); ts.hasNext();) {
CGNode tn = (CGNode) ts.next(); CGNode tn = (CGNode) ts.next();
if (!relevant.accepts(tn)) { if (!relevant.accepts(tn)) {
if (DEBUG_LEVEL > 0) { if (DEBUG_LEVEL > 0) {
@ -490,7 +490,7 @@ public class InterproceduralCFG implements NumberedGraph<BasicBlockInContext> {
IInvokeInstruction call = (IInvokeInstruction) cinsts[i]; IInvokeInstruction call = (IInvokeInstruction) cinsts[i];
CallSiteReference site = makeCallSiteReference(n.getMethod().getDeclaringClass().getClassLoader().getReference(), ccfg CallSiteReference site = makeCallSiteReference(n.getMethod().getDeclaringClass().getClassLoader().getReference(), ccfg
.getProgramCounter(i), call); .getProgramCounter(i), call);
if (caller.getPossibleTargets(site).contains(n)) { if (cg.getPossibleTargets(caller, site).contains(n)) {
if (DEBUG_LEVEL > 0) { if (DEBUG_LEVEL > 0) {
Trace.println("Adding edge " + ccfg.getBlockForInstruction(i) + " to " + bb); Trace.println("Adding edge " + ccfg.getBlockForInstruction(i) + " to " + bb);
} }
@ -701,7 +701,6 @@ public class InterproceduralCFG implements NumberedGraph<BasicBlockInContext> {
} }
/** /**
* @param B
* @return the set of CGNodes that B may call, according to the governing call * @return the set of CGNodes that B may call, according to the governing call
* graph. * graph.
*/ */
@ -710,8 +709,8 @@ public class InterproceduralCFG implements NumberedGraph<BasicBlockInContext> {
IInvokeInstruction call = (IInvokeInstruction) statements[B.getLastInstructionIndex()]; IInvokeInstruction call = (IInvokeInstruction) statements[B.getLastInstructionIndex()];
int pc = cfg.getProgramCounter(B.getLastInstructionIndex()); int pc = cfg.getProgramCounter(B.getLastInstructionIndex());
CallSiteReference site = makeCallSiteReference(B.getMethod().getDeclaringClass().getClassLoader().getReference(), pc, call); CallSiteReference site = makeCallSiteReference(B.getMethod().getDeclaringClass().getClassLoader().getReference(), pc, call);
HashSet<CGNode> result = HashSetFactory.make(Bnode.getNumberOfTargets(site)); HashSet<CGNode> result = HashSetFactory.make(cg.getNumberOfTargets(Bnode,site));
for (Iterator<CGNode> it = Bnode.getPossibleTargets(site).iterator(); it.hasNext();) { for (Iterator<CGNode> it = cg.getPossibleTargets(Bnode,site).iterator(); it.hasNext();) {
CGNode target = it.next(); CGNode target = it.next();
result.add(target); result.add(target);
} }

View File

@ -28,6 +28,7 @@ import com.ibm.wala.dataflow.graph.ITransferFunctionProvider;
import com.ibm.wala.fixedpoint.impl.UnaryOperator; import com.ibm.wala.fixedpoint.impl.UnaryOperator;
import com.ibm.wala.fixpoint.BitVectorVariable; import com.ibm.wala.fixpoint.BitVectorVariable;
import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.callgraph.propagation.PointerKey; import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
import com.ibm.wala.ipa.callgraph.propagation.StaticFieldKey; import com.ibm.wala.ipa.callgraph.propagation.StaticFieldKey;
@ -93,7 +94,7 @@ public class HeapReachingDefs {
* if statements is null * if statements is null
*/ */
public static Map<Statement, OrdinalSet<Statement>> computeReachingDefs(CGNode node, IR ir, PointerAnalysis pa, public static Map<Statement, OrdinalSet<Statement>> computeReachingDefs(CGNode node, IR ir, PointerAnalysis pa,
Map<CGNode, OrdinalSet<PointerKey>> mod, Collection<Statement> statements, HeapExclusions exclusions) { Map<CGNode, OrdinalSet<PointerKey>> mod, Collection<Statement> statements, HeapExclusions exclusions, CallGraph cg) {
if (statements == null) { if (statements == null) {
throw new IllegalArgumentException("statements is null"); throw new IllegalArgumentException("statements is null");
@ -129,21 +130,24 @@ public class HeapReachingDefs {
System.err.println("Solved. "); System.err.println("Solved. ");
} }
return makeResult(solver, domain, node, new DelegatingExtendedHeapModel(pa.getHeapModel()), pa, mod, cfg, return makeResult(solver, domain, node, new DelegatingExtendedHeapModel(pa.getHeapModel()), pa, mod, cfg,
ssaInstructionIndex2Statement, exclusions); ssaInstructionIndex2Statement, exclusions, cg);
} }
private static class RDMap implements Map<Statement, OrdinalSet<Statement>> { private static class RDMap implements Map<Statement, OrdinalSet<Statement>> {
final Map<Statement, OrdinalSet<Statement>> delegate = HashMapFactory.make(); final Map<Statement, OrdinalSet<Statement>> delegate = HashMapFactory.make();
private final HeapExclusions exclusions; private final HeapExclusions exclusions;
private final CallGraph cg;
RDMap(BitVectorSolver<IBasicBlock> solver, OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h, RDMap(BitVectorSolver<IBasicBlock> solver, OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h,
PointerAnalysis pa, Map<CGNode, OrdinalSet<PointerKey>> mod, ExpandedControlFlowGraph cfg, PointerAnalysis pa, Map<CGNode, OrdinalSet<PointerKey>> mod, ExpandedControlFlowGraph cfg,
Map<Integer, NormalStatement> ssaInstructionIndex2Statement, HeapExclusions exclusions) { Map<Integer, NormalStatement> ssaInstructionIndex2Statement, HeapExclusions exclusions, CallGraph cg) {
if (VERBOSE) { if (VERBOSE) {
System.err.println("Init pointer Key mod "); System.err.println("Init pointer Key mod ");
} }
this.exclusions = exclusions; this.exclusions = exclusions;
this.cg = cg;
Map<PointerKey, MutableIntSet> pointerKeyMod = initPointerKeyMod(domain, node, h, pa); Map<PointerKey, MutableIntSet> pointerKeyMod = initPointerKeyMod(domain, node, h, pa);
if (VERBOSE) { if (VERBOSE) {
System.err.println("Eager populate"); System.err.println("Eager populate");
@ -313,7 +317,7 @@ public class HeapReachingDefs {
HeapStatement.ReturnCaller r = (HeapStatement.ReturnCaller) s; HeapStatement.ReturnCaller r = (HeapStatement.ReturnCaller) s;
IBasicBlock bb = cfg.getBlockForInstruction(r.getCall()); IBasicBlock bb = cfg.getBlockForInstruction(r.getCall());
BitVectorVariable v = (BitVectorVariable) solver.getIn(bb); BitVectorVariable v = (BitVectorVariable) solver.getIn(bb);
if (allCalleesMod(r, mod) || pointerKeyMod.get(r.getLocation()) == null || v.getValue() == null) { if (allCalleesMod(cg, r, mod) || pointerKeyMod.get(r.getLocation()) == null || v.getValue() == null) {
// do nothing ... force flow into and out of the callees // do nothing ... force flow into and out of the callees
return OrdinalSet.empty(); return OrdinalSet.empty();
} else { } else {
@ -364,19 +368,17 @@ public class HeapReachingDefs {
private static Map<Statement, OrdinalSet<Statement>> makeResult(BitVectorSolver<IBasicBlock> solver, private static Map<Statement, OrdinalSet<Statement>> makeResult(BitVectorSolver<IBasicBlock> solver,
OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h, PointerAnalysis pa, OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h, PointerAnalysis pa,
Map<CGNode, OrdinalSet<PointerKey>> mod, ExpandedControlFlowGraph cfg, Map<CGNode, OrdinalSet<PointerKey>> mod, ExpandedControlFlowGraph cfg,
Map<Integer, NormalStatement> ssaInstructionIndex2Statement, HeapExclusions exclusions) { Map<Integer, NormalStatement> ssaInstructionIndex2Statement, HeapExclusions exclusions, CallGraph cg) {
return new RDMap(solver, domain, node, h, pa, mod, cfg, ssaInstructionIndex2Statement, exclusions); return new RDMap(solver, domain, node, h, pa, mod, cfg, ssaInstructionIndex2Statement, exclusions, cg);
} }
/** /**
* Do all callees corresponding to the given call site def the pointer key * Do all callees corresponding to the given call site def the pointer key
* being tracked by r? * being tracked by r?
*
* @param mod
*/ */
private static boolean allCalleesMod(ReturnCaller r, Map<CGNode, OrdinalSet<PointerKey>> mod) { private static boolean allCalleesMod(CallGraph cg, ReturnCaller r, Map<CGNode, OrdinalSet<PointerKey>> mod) {
Collection<CGNode> targets = r.getNode().getPossibleTargets(r.getCall().getCallSite()); Collection<CGNode> targets = cg.getPossibleTargets(r.getNode(), r.getCall().getCallSite());
if (targets.isEmpty()) { if (targets.isEmpty()) {
return false; return false;
} }

View File

@ -21,6 +21,7 @@ import com.ibm.wala.cfg.cdg.ControlDependenceGraph;
import com.ibm.wala.classLoader.CallSiteReference; import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IClass; import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
import com.ibm.wala.ipa.callgraph.impl.SetOfClasses; import com.ibm.wala.ipa.callgraph.impl.SetOfClasses;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis; import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.ipa.callgraph.propagation.PointerKey; import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
@ -96,6 +97,8 @@ public class PDG extends SlowSparseNumberedGraph<Statement> {
private final Map<CGNode, OrdinalSet<PointerKey>> mod; private final Map<CGNode, OrdinalSet<PointerKey>> mod;
private final DataDependenceOptions dOptions; private final DataDependenceOptions dOptions;
private final CallGraph cg;
/** /**
* @param mod * @param mod
@ -109,12 +112,13 @@ public class PDG extends SlowSparseNumberedGraph<Statement> {
*/ */
public PDG(final CGNode node, PointerAnalysis pa, Map<CGNode, OrdinalSet<PointerKey>> mod, public PDG(final CGNode node, PointerAnalysis pa, Map<CGNode, OrdinalSet<PointerKey>> mod,
Map<CGNode, OrdinalSet<PointerKey>> ref, DataDependenceOptions dOptions, ControlDependenceOptions cOptions, Map<CGNode, OrdinalSet<PointerKey>> ref, DataDependenceOptions dOptions, ControlDependenceOptions cOptions,
HeapExclusions exclusions) { HeapExclusions exclusions, CallGraph cg) {
super(); super();
if (node == null) { if (node == null) {
throw new IllegalArgumentException("node is null"); throw new IllegalArgumentException("node is null");
} }
this.cg = cg;
this.node = node; this.node = node;
this.heapModel = pa == null ? null : new DelegatingExtendedHeapModel(pa.getHeapModel()); this.heapModel = pa == null ? null : new DelegatingExtendedHeapModel(pa.getHeapModel());
this.pa = pa; this.pa = pa;
@ -493,7 +497,7 @@ public class PDG extends SlowSparseNumberedGraph<Statement> {
Collection<Statement> relevantStatements = Iterator2Collection.toCollection(new FilterIterator<Statement>(iterator(), f)); Collection<Statement> relevantStatements = Iterator2Collection.toCollection(new FilterIterator<Statement>(iterator(), f));
Map<Statement, OrdinalSet<Statement>> heapReachingDefs = dOptions.isIgnoreHeap() ? null : HeapReachingDefs.computeReachingDefs( Map<Statement, OrdinalSet<Statement>> heapReachingDefs = dOptions.isIgnoreHeap() ? null : HeapReachingDefs.computeReachingDefs(
node, ir, pa, mod, relevantStatements, new HeapExclusions(SetComplement.complement(new SingletonSet(t)))); node, ir, pa, mod, relevantStatements, new HeapExclusions(SetComplement.complement(new SingletonSet(t))), cg);
for (Statement st : heapReachingDefs.keySet()) { for (Statement st : heapReachingDefs.keySet()) {
switch (st.getKind()) { switch (st.getKind()) {
@ -829,13 +833,13 @@ public class PDG extends SlowSparseNumberedGraph<Statement> {
} }
if (!dOptions.isIgnoreHeap()) { if (!dOptions.isIgnoreHeap()) {
OrdinalSet<PointerKey> uref = unionHeapLocations(node, call, ref); OrdinalSet<PointerKey> uref = unionHeapLocations(cg, node, call, ref);
for (PointerKey p : uref) { for (PointerKey p : uref) {
Statement st = new HeapStatement.ParamCaller(node, callIndex, p); Statement st = new HeapStatement.ParamCaller(node, callIndex, p);
addNode(st); addNode(st);
params.add(st); params.add(st);
} }
OrdinalSet<PointerKey> umod = unionHeapLocations(node, call, mod); OrdinalSet<PointerKey> umod = unionHeapLocations(cg, node, call, mod);
for (PointerKey p : umod) { for (PointerKey p : umod) {
Statement st = new HeapStatement.ReturnCaller(node, callIndex, p); Statement st = new HeapStatement.ReturnCaller(node, callIndex, p);
addNode(st); addNode(st);
@ -847,10 +851,10 @@ public class PDG extends SlowSparseNumberedGraph<Statement> {
/** /**
* @return the set of all locations read by any callee at a call site. * @return the set of all locations read by any callee at a call site.
*/ */
private OrdinalSet<PointerKey> unionHeapLocations(CGNode n, SSAAbstractInvokeInstruction call, private OrdinalSet<PointerKey> unionHeapLocations(CallGraph cg, CGNode n, SSAAbstractInvokeInstruction call,
Map<CGNode, OrdinalSet<PointerKey>> loc) { Map<CGNode, OrdinalSet<PointerKey>> loc) {
BitVectorIntSet bv = new BitVectorIntSet(); BitVectorIntSet bv = new BitVectorIntSet();
for (CGNode t : n.getPossibleTargets(call.getCallSite())) { for (CGNode t : cg.getPossibleTargets(n, call.getCallSite())) {
bv.addAll(loc.get(t).getBackingSet()); bv.addAll(loc.get(t).getBackingSet());
} }
return new OrdinalSet<PointerKey>(bv, loc.get(n).getMapping()); return new OrdinalSet<PointerKey>(bv, loc.get(n).getMapping());

View File

@ -212,7 +212,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
Collection<Statement> result = Iterator2Collection.toCollection(getPDG(N.getNode()).getPredNodes(N)); Collection<Statement> result = Iterator2Collection.toCollection(getPDG(N.getNode()).getPredNodes(N));
if (!dOptions.equals(DataDependenceOptions.NONE)) { if (!dOptions.equals(DataDependenceOptions.NONE)) {
// data dependence predecessors // data dependence predecessors
for (CGNode t : N.getNode().getPossibleTargets(call.getCallSite())) { for (CGNode t : cg.getPossibleTargets(N.getNode(),call.getCallSite())) {
Statement s = new ParamStatement.ExceptionalReturnCallee(t); Statement s = new ParamStatement.ExceptionalReturnCallee(t);
addNode(s); addNode(s);
result.add(s); result.add(s);
@ -226,7 +226,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
Collection<Statement> result = Iterator2Collection.toCollection(getPDG(N.getNode()).getPredNodes(N)); Collection<Statement> result = Iterator2Collection.toCollection(getPDG(N.getNode()).getPredNodes(N));
if (!dOptions.equals(DataDependenceOptions.NONE)) { if (!dOptions.equals(DataDependenceOptions.NONE)) {
// data dependence predecessors // data dependence predecessors
for (CGNode t : N.getNode().getPossibleTargets(call.getCallSite())) { for (CGNode t : cg.getPossibleTargets(N.getNode(), call.getCallSite())) {
Statement s = new ParamStatement.NormalReturnCallee(t); Statement s = new ParamStatement.NormalReturnCallee(t);
addNode(s); addNode(s);
result.add(s); result.add(s);
@ -240,7 +240,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
Collection<Statement> result = Iterator2Collection.toCollection(getPDG(N.getNode()).getPredNodes(N)); Collection<Statement> result = Iterator2Collection.toCollection(getPDG(N.getNode()).getPredNodes(N));
if (!dOptions.equals(DataDependenceOptions.NONE)) { if (!dOptions.equals(DataDependenceOptions.NONE)) {
// data dependence predecessors // data dependence predecessors
for (CGNode t : N.getNode().getPossibleTargets(call.getCallSite())) { for (CGNode t : cg.getPossibleTargets(N.getNode(), call.getCallSite())) {
if (mod.get(t).contains(r.getLocation())) { if (mod.get(t).contains(r.getLocation())) {
Statement s = new HeapStatement.ReturnCallee(t, r.getLocation()); Statement s = new HeapStatement.ReturnCallee(t, r.getLocation());
addNode(s); addNode(s);
@ -258,7 +258,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
// data dependence predecessors // data dependence predecessors
for (Iterator<? extends CGNode> it = cg.getPredNodes(N.getNode()); it.hasNext();) { for (Iterator<? extends CGNode> it = cg.getPredNodes(N.getNode()); it.hasNext();) {
CGNode caller = it.next(); CGNode caller = it.next();
for (Iterator<CallSiteReference> it2 = caller.getPossibleSites(N.getNode()); it2.hasNext();) { for (Iterator<CallSiteReference> it2 = cg.getPossibleSites(caller, N.getNode()); it2.hasNext();) {
CallSiteReference site = it2.next(); CallSiteReference site = it2.next();
IR ir = caller.getIR(); IR ir = caller.getIR();
IntSet indices = ir.getCallInstructionIndices(site); IntSet indices = ir.getCallInstructionIndices(site);
@ -287,7 +287,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
// data dependence predecessors // data dependence predecessors
for (Iterator<? extends CGNode> it = cg.getPredNodes(N.getNode()); it.hasNext();) { for (Iterator<? extends CGNode> it = cg.getPredNodes(N.getNode()); it.hasNext();) {
CGNode caller = it.next(); CGNode caller = it.next();
for (Iterator<CallSiteReference> it2 = caller.getPossibleSites(N.getNode()); it2.hasNext();) { for (Iterator<CallSiteReference> it2 = cg.getPossibleSites(caller, N.getNode()); it2.hasNext();) {
CallSiteReference site = it2.next(); CallSiteReference site = it2.next();
IR ir = caller.getIR(); IR ir = caller.getIR();
IntSet indices = ir.getCallInstructionIndices(site); IntSet indices = ir.getCallInstructionIndices(site);
@ -312,7 +312,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
if (!cOptions.equals(ControlDependenceOptions.NONE)) { if (!cOptions.equals(ControlDependenceOptions.NONE)) {
for (Iterator<? extends CGNode> it = cg.getPredNodes(N.getNode()); it.hasNext();) { for (Iterator<? extends CGNode> it = cg.getPredNodes(N.getNode()); it.hasNext();) {
CGNode caller = it.next(); CGNode caller = it.next();
for (Iterator<CallSiteReference> it2 = caller.getPossibleSites(N.getNode()); it2.hasNext();) { for (Iterator<CallSiteReference> it2 = cg.getPossibleSites(caller, N.getNode()); it2.hasNext();) {
CallSiteReference site = it2.next(); CallSiteReference site = it2.next();
IR ir = caller.getIR(); IR ir = caller.getIR();
IntSet indices = ir.getCallInstructionIndices(site); IntSet indices = ir.getCallInstructionIndices(site);
@ -346,7 +346,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
if (ns.getInstruction() instanceof SSAAbstractInvokeInstruction) { if (ns.getInstruction() instanceof SSAAbstractInvokeInstruction) {
HashSet<Statement> result = HashSetFactory.make(); HashSet<Statement> result = HashSetFactory.make();
SSAAbstractInvokeInstruction call = (SSAAbstractInvokeInstruction) ns.getInstruction(); SSAAbstractInvokeInstruction call = (SSAAbstractInvokeInstruction) ns.getInstruction();
for (CGNode t : N.getNode().getPossibleTargets(call.getCallSite())) { for (CGNode t : cg.getPossibleTargets(N.getNode(), call.getCallSite())) {
Statement s = new MethodEntryStatement(t); Statement s = new MethodEntryStatement(t);
addNode(s); addNode(s);
result.add(s); result.add(s);
@ -371,7 +371,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
// data dependence predecessors // data dependence predecessors
for (Iterator<? extends CGNode> it = cg.getPredNodes(N.getNode()); it.hasNext();) { for (Iterator<? extends CGNode> it = cg.getPredNodes(N.getNode()); it.hasNext();) {
CGNode caller = it.next(); CGNode caller = it.next();
for (Iterator<CallSiteReference> it2 = caller.getPossibleSites(N.getNode()); it2.hasNext();) { for (Iterator<CallSiteReference> it2 = cg.getPossibleSites(caller, N.getNode()); it2.hasNext();) {
CallSiteReference site = it2.next(); CallSiteReference site = it2.next();
IR ir = caller.getIR(); IR ir = caller.getIR();
IntSet indices = ir.getCallInstructionIndices(site); IntSet indices = ir.getCallInstructionIndices(site);
@ -393,7 +393,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
// data dependence predecessors // data dependence predecessors
for (Iterator<? extends CGNode> it = cg.getPredNodes(N.getNode()); it.hasNext();) { for (Iterator<? extends CGNode> it = cg.getPredNodes(N.getNode()); it.hasNext();) {
CGNode caller = it.next(); CGNode caller = it.next();
for (Iterator<CallSiteReference> it2 = caller.getPossibleSites(N.getNode()); it2.hasNext();) { for (Iterator<CallSiteReference> it2 = cg.getPossibleSites(caller, N.getNode()); it2.hasNext();) {
CallSiteReference site = it2.next(); CallSiteReference site = it2.next();
IR ir = caller.getIR(); IR ir = caller.getIR();
IntSet indices = ir.getCallInstructionIndices(site); IntSet indices = ir.getCallInstructionIndices(site);
@ -416,7 +416,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
// data dependence predecessors // data dependence predecessors
for (Iterator<? extends CGNode> it = cg.getPredNodes(N.getNode()); it.hasNext();) { for (Iterator<? extends CGNode> it = cg.getPredNodes(N.getNode()); it.hasNext();) {
CGNode caller = it.next(); CGNode caller = it.next();
for (Iterator<CallSiteReference> it2 = caller.getPossibleSites(N.getNode()); it2.hasNext();) { for (Iterator<CallSiteReference> it2 = cg.getPossibleSites(caller, N.getNode()); it2.hasNext();) {
CallSiteReference site = it2.next(); CallSiteReference site = it2.next();
IR ir = caller.getIR(); IR ir = caller.getIR();
IntSet indices = ir.getCallInstructionIndices(site); IntSet indices = ir.getCallInstructionIndices(site);
@ -437,7 +437,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
Collection<Statement> result = HashSetFactory.make(5); Collection<Statement> result = HashSetFactory.make(5);
if (!dOptions.equals(DataDependenceOptions.NONE)) { if (!dOptions.equals(DataDependenceOptions.NONE)) {
// data dependence successors // data dependence successors
for (CGNode t : N.getNode().getPossibleTargets(call.getCallSite())) { for (CGNode t : cg.getPossibleTargets(N.getNode(), call.getCallSite())) {
for (int i = 0; i < t.getMethod().getNumberOfParameters(); i++) { for (int i = 0; i < t.getMethod().getNumberOfParameters(); i++) {
if (call.getUse(i) == pac.getValueNumber()) { if (call.getUse(i) == pac.getValueNumber()) {
Statement s = new ParamStatement.ParamCallee(t, i + 1); Statement s = new ParamStatement.ParamCallee(t, i + 1);
@ -455,7 +455,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
Collection<Statement> result = HashSetFactory.make(5); Collection<Statement> result = HashSetFactory.make(5);
if (!dOptions.equals(DataDependenceOptions.NONE)) { if (!dOptions.equals(DataDependenceOptions.NONE)) {
// data dependence successors // data dependence successors
for (CGNode t : N.getNode().getPossibleTargets(call.getCallSite())) { for (CGNode t : cg.getPossibleTargets(N.getNode(), call.getCallSite())) {
if (ref.get(t).contains(pc.getLocation())) { if (ref.get(t).contains(pc.getLocation())) {
Statement s = new HeapStatement.ParamCallee(t, pc.getLocation()); Statement s = new HeapStatement.ParamCallee(t, pc.getLocation());
addNode(s); addNode(s);
@ -480,7 +480,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
if (dst instanceof MethodEntryStatement) { if (dst instanceof MethodEntryStatement) {
if (ns.getInstruction() instanceof SSAAbstractInvokeInstruction) { if (ns.getInstruction() instanceof SSAAbstractInvokeInstruction) {
SSAAbstractInvokeInstruction call = (SSAAbstractInvokeInstruction) ns.getInstruction(); SSAAbstractInvokeInstruction call = (SSAAbstractInvokeInstruction) ns.getInstruction();
return src.getNode().getPossibleTargets(call.getCallSite()).contains(dst.getNode()); return cg.getPossibleTargets(src.getNode(), call.getCallSite()).contains(dst.getNode());
} else { } else {
return false; return false;
} }
@ -502,7 +502,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
} }
if (dst.getKind().equals(Kind.EXC_RET_CALLER)) { if (dst.getKind().equals(Kind.EXC_RET_CALLER)) {
ParamStatement.ExceptionalReturnCaller r = (ParamStatement.ExceptionalReturnCaller) dst; ParamStatement.ExceptionalReturnCaller r = (ParamStatement.ExceptionalReturnCaller) dst;
return r.getNode().getPossibleTargets(r.getCall().getCallSite()).contains(src.getNode()); return cg.getPossibleTargets(r.getNode(), r.getCall().getCallSite()).contains(src.getNode());
} else { } else {
return false; return false;
} }
@ -513,7 +513,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
} }
if (dst.getKind().equals(Kind.NORMAL_RET_CALLER)) { if (dst.getKind().equals(Kind.NORMAL_RET_CALLER)) {
ParamStatement.NormalReturnCaller r = (ParamStatement.NormalReturnCaller) dst; ParamStatement.NormalReturnCaller r = (ParamStatement.NormalReturnCaller) dst;
return r.getNode().getPossibleTargets(r.getCall().getCallSite()).contains(src.getNode()); return cg.getPossibleTargets(r.getNode(), r.getCall().getCallSite()).contains(src.getNode());
} else { } else {
return false; return false;
} }
@ -526,7 +526,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
HeapStatement.ReturnCaller r = (HeapStatement.ReturnCaller) dst; HeapStatement.ReturnCaller r = (HeapStatement.ReturnCaller) dst;
HeapStatement h = (HeapStatement) src; HeapStatement h = (HeapStatement) src;
return h.getLocation().equals(r.getLocation()) return h.getLocation().equals(r.getLocation())
&& r.getNode().getPossibleTargets(r.getCall().getCallSite()).contains(src.getNode()); && cg.getPossibleTargets(r.getNode(), r.getCall().getCallSite()).contains(src.getNode());
} else { } else {
return false; return false;
} }
@ -540,7 +540,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
ParamStatement.ParamCaller caller = (ParamStatement.ParamCaller) src; ParamStatement.ParamCaller caller = (ParamStatement.ParamCaller) src;
return caller.getValueNumber() == callee.getValueNumber() return caller.getValueNumber() == callee.getValueNumber()
&& caller.getNode().getPossibleTargets(caller.getCall().getCallSite()).contains(callee.getNode()); && cg.getPossibleTargets(caller.getNode(), caller.getCall().getCallSite()).contains(callee.getNode());
} else { } else {
return false; return false;
} }
@ -554,7 +554,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
HeapStatement.ParamCaller caller = (HeapStatement.ParamCaller) src; HeapStatement.ParamCaller caller = (HeapStatement.ParamCaller) src;
return caller.getLocation().equals(callee.getLocation()) return caller.getLocation().equals(callee.getLocation())
&& caller.getNode().getPossibleTargets(caller.getCall().getCallSite()).contains(callee.getNode()); && cg.getPossibleTargets(caller.getNode(), caller.getCall().getCallSite()).contains(callee.getNode());
} else { } else {
return false; return false;
} }
@ -618,7 +618,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
public PDG getPDG(CGNode node) { public PDG getPDG(CGNode node) {
PDG result = pdgMap.get(node); PDG result = pdgMap.get(node);
if (result == null) { if (result == null) {
result = new PDG(node, pa, mod, ref, dOptions, cOptions, heapExclude); result = new PDG(node, pa, mod, ref, dOptions, cOptions, heapExclude, cg);
pdgMap.put(node, result); pdgMap.put(node, result);
for (Iterator<? extends Statement> it = result.iterator(); it.hasNext();) { for (Iterator<? extends Statement> it = result.iterator(); it.hasNext();) {
nodeMgr.addNode(it.next()); nodeMgr.addNode(it.next());
@ -631,4 +631,8 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
return cOptions; return cOptions;
} }
public CallGraph getCallGraph() {
return cg;
}
} }