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:
parent
d72e0a1752
commit
fd1a1d4cae
|
@ -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()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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();) {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue