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();) {
CallSiteReference site = (CallSiteReference) it2.next();
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();
result.addEdge(eSite, makeJavaMethod(target.getMethod().getReference()));
}

View File

@ -11,7 +11,6 @@
package com.ibm.wala.ipa.callgraph;
import java.util.Iterator;
import java.util.Set;
import com.ibm.wala.cfg.ControlFlowGraph;
import com.ibm.wala.classLoader.CallSiteReference;
@ -44,40 +43,44 @@ public interface CGNode extends INodeWithNumber, ContextItem {
*/
public Context getContext();
/**
* Return the set of CGNodes that represent possible targets
* of a particular call site when invoked in this context.
*/
Set<CGNode> getPossibleTargets(CallSiteReference site);
// /**
// * Return the set of CGNodes that represent possible targets
// * of a particular call site when invoked in this context.
// */
// Set<CGNode> getPossibleTargets(CallSiteReference site);
/**
* @return Iterator of CallSiteReference
*/
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
* @return iterator of CallSiteReference, the call sites in this node that might
* dispatch to the target node.
*/
Iterator<CallSiteReference> getPossibleSites(CGNode target);
/**
* This is for use only by call graph builders ... not by the general
* public. Clients should not use this.
*
* Record that a particular call site might resolve to a call to a
* particular target node. Returns true if this is a new target
*/
@Deprecated
public boolean addTarget(CallSiteReference site, CGNode target);
/**
* @return the number of nodes that the call site current may resolve
* to
*/
public int getNumberOfTargets(CallSiteReference site);
// /**
// * @return the number of nodes that the call site current may resolve
// * to
// */
// public int getNumberOfTargets(CallSiteReference site);
/**
* @return the call graph in which this node dwells
*/
public CallGraph getCallGraph();
// /**
// * @return the call graph in which this node dwells
// */
// public CallGraph getCallGraph();
/**
* @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;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.cha.IClassHierarchy;
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
*
*
*
* @author Stephen Fink
*/
public interface CallGraph extends NumberedGraph<CGNode> {
/**
* Return the (fake) interprocedural {@link CGNode root node}
* of the call graph.
*
* Return the (fake) interprocedural {@link CGNode root node} of the call
* graph.
*
* @return the "fake" root node the call graph
*/
public CGNode getFakeRootNode();
@ -40,29 +42,40 @@ public interface CallGraph extends NumberedGraph<CGNode> {
public Collection<CGNode> getEntrypointNodes();
/**
* If you want to get <em> all </em> the nodes corresponding to
* a particular method, regardless of context, then use
* {@link CGNode getNodes}
* If you want to get <em> all </em> the nodes corresponding to a particular
* method, regardless of context, then use {@link CGNode getNodes}
*
* @return the node corresponding a method in a context
*/
public CGNode getNode(IMethod method, Context C);
/**
* @param m a method reference
* @return the set of all nodes in the call graph that represent
* this method.
* @param m
* a method reference
* @return the set of all nodes in the call graph that represent this method.
*/
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
*/
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;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@ -94,9 +90,7 @@ public abstract class BasicCallGraph extends AbstractNumberedGraph<CGNode> imple
super();
}
/**
*
*/
@SuppressWarnings("deprecation")
public void init() {
fakeRoot = makeFakeRootNode();
Key k = new Key(fakeRoot.getMethod(), fakeRoot.getContext());
@ -197,8 +191,6 @@ public abstract class BasicCallGraph extends AbstractNumberedGraph<CGNode> imple
return method;
}
public abstract Set<CGNode> getPossibleTargets(CallSiteReference site);
/**
* @see java.lang.Object#equals(Object)
*/
@ -236,7 +228,7 @@ public abstract class BasicCallGraph extends AbstractNumberedGraph<CGNode> imple
if (n.getMethod() != null) {
for (Iterator sites = n.iterateSites(); sites.hasNext();) {
CallSiteReference site = (CallSiteReference) sites.next();
Iterator targets = n.getPossibleTargets(site).iterator();
Iterator targets = getPossibleTargets(n, site).iterator();
if (targets.hasNext()) {
result.append(" - " + site + "\n");
}
@ -250,38 +242,6 @@ public abstract class BasicCallGraph extends AbstractNumberedGraph<CGNode> imple
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
public void removeNodeAndEdges(CGNode N) {
Assertions.UNREACHABLE();

View File

@ -146,8 +146,7 @@ public class ExplicitCallGraph extends BasicCallGraph implements BytecodeConstan
super(method, C);
}
@Override
public Set<CGNode> getPossibleTargets(CallSiteReference site) {
protected Set<CGNode> getPossibleTargets(CallSiteReference site) {
Object result = targets.get(site.getProgramCounter());
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());
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)
*/
public Iterator<CallSiteReference> getPossibleSites(final CGNode to) {
protected Iterator<CallSiteReference> getPossibleSites(final CGNode to) {
final int n = getCallGraph().getNumber(to);
return new FilterIterator<CallSiteReference>(iterateSites(), new Filter() {
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
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()
@ -295,7 +293,7 @@ public class ExplicitCallGraph extends BasicCallGraph implements BytecodeConstan
return getMethod().hashCode() * 8681 + getContext().hashCode();
}
public MutableSharedBitVectorIntSet getAllTargetNumbers() {
protected MutableSharedBitVectorIntSet getAllTargetNumbers() {
return allTargets;
}
@ -441,4 +439,43 @@ public class ExplicitCallGraph extends BasicCallGraph implements BytecodeConstan
protected ExplicitEdgeManager makeEdgeManger() {
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.Set;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.CallGraph;
@ -125,4 +126,19 @@ public class PartialCallGraph extends DelegatingGraph<CGNode> implements CallGra
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
* particular call site
*/
private OrdinalSet<InstanceKey> computeImplicitExceptionsForCall(CGNode node, SSAInvokeInstruction call) {
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();
PointerKey retVal = pointerKeys.getPointerKeyForExceptionalReturnValue(target);
IntSet set = getPointsToSet(retVal).getBackingSet();

View File

@ -461,7 +461,7 @@ public class PointerFlowGraph extends AbstractGraph<PointerKey> {
@Override
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();
// 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
* exceptions from this call site.
*/
@SuppressWarnings("deprecation")
private void processResolvedCall(CGNode caller, SSAAbstractInvokeInstruction instruction, CGNode target,
InstanceKey[][] constParams, PointerKey uniqueCatchKey) {
@ -1660,7 +1661,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
Trace.println("Warning: null target for call " + call + " " + iKey);
}
} else {
IntSet targets = node.getPossibleTargetNumbers(call.getCallSite());
IntSet targets = getCallGraph().getPossibleTargetNumbers(node,call.getCallSite());
if (targets != null && targets.contains(target.getGraphNodeId())) {
// do nothing; we've previously discovered and handled this
// receiver for this call site.
@ -1703,7 +1704,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
private boolean willNeverChangeAgain(IntSet receivers) {
int bound = getBoundOnNumberOfTargets(node, call.getSite());
if (bound > -1) {
int nTargets = node.getNumberOfTargets(call.getSite());
int nTargets = getCallGraph().getNumberOfTargets(node, call.getSite());
if (Assertions.verifyAssertions) {
if (nTargets > bound) {
Trace.println("node: " + node);
@ -1711,7 +1712,7 @@ public abstract class SSAPropagationCallGraphBuilder extends PropagationCallGrap
Trace.println("instruction " + call);
Trace.println("nTargets: " + nTargets);
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());
}
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.
*/
@SuppressWarnings("deprecation")
void processResolvedCall(CGNode caller, CallSiteReference site, CGNode target) {
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())) {
// do nothing; we've previously discovered and handled this
// receiver for this call site.

View File

@ -79,7 +79,7 @@ public class DelegatingExplicitCallGraph extends ExplicitCallGraph {
Object n = it.next();
if (n instanceof CallSite) {
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) {
result.addAll(s);
}
@ -98,7 +98,7 @@ public class DelegatingExplicitCallGraph extends ExplicitCallGraph {
CallSite p = (CallSite) result;
CGNode n = p.getNode();
CallSiteReference s = p.getSite();
return n.getPossibleTargets(s);
return DelegatingExplicitCallGraph.this.getPossibleTargets(n, s);
} else {
return super.getPossibleTargets(site);
}
@ -125,7 +125,7 @@ public class DelegatingExplicitCallGraph extends ExplicitCallGraph {
Object n = it.next();
if (n instanceof CallSite) {
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)) {
return true;
}
@ -142,7 +142,7 @@ public class DelegatingExplicitCallGraph extends ExplicitCallGraph {
CallSite p = (CallSite) result;
CGNode n = p.getNode();
CallSiteReference s = p.getSite();
return n.getNumberOfTargets(s);
return DelegatingExplicitCallGraph.this.getNumberOfTargets(n,s);
} else {
return super.getNumberOfTargets(site);
}

View File

@ -277,7 +277,7 @@ public class InterproceduralCFG implements NumberedGraph<BasicBlockInContext> {
Trace.println("got Site: " + site);
}
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();
if (!relevant.accepts(tn)) {
if (DEBUG_LEVEL > 0) {
@ -490,7 +490,7 @@ public class InterproceduralCFG implements NumberedGraph<BasicBlockInContext> {
IInvokeInstruction call = (IInvokeInstruction) cinsts[i];
CallSiteReference site = makeCallSiteReference(n.getMethod().getDeclaringClass().getClassLoader().getReference(), ccfg
.getProgramCounter(i), call);
if (caller.getPossibleTargets(site).contains(n)) {
if (cg.getPossibleTargets(caller, site).contains(n)) {
if (DEBUG_LEVEL > 0) {
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
* graph.
*/
@ -710,8 +709,8 @@ public class InterproceduralCFG implements NumberedGraph<BasicBlockInContext> {
IInvokeInstruction call = (IInvokeInstruction) statements[B.getLastInstructionIndex()];
int pc = cfg.getProgramCounter(B.getLastInstructionIndex());
CallSiteReference site = makeCallSiteReference(B.getMethod().getDeclaringClass().getClassLoader().getReference(), pc, call);
HashSet<CGNode> result = HashSetFactory.make(Bnode.getNumberOfTargets(site));
for (Iterator<CGNode> it = Bnode.getPossibleTargets(site).iterator(); it.hasNext();) {
HashSet<CGNode> result = HashSetFactory.make(cg.getNumberOfTargets(Bnode,site));
for (Iterator<CGNode> it = cg.getPossibleTargets(Bnode,site).iterator(); it.hasNext();) {
CGNode target = it.next();
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.fixpoint.BitVectorVariable;
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.PointerKey;
import com.ibm.wala.ipa.callgraph.propagation.StaticFieldKey;
@ -93,7 +94,7 @@ public class HeapReachingDefs {
* if statements is null
*/
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) {
throw new IllegalArgumentException("statements is null");
@ -129,21 +130,24 @@ public class HeapReachingDefs {
System.err.println("Solved. ");
}
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>> {
final Map<Statement, OrdinalSet<Statement>> delegate = HashMapFactory.make();
private final HeapExclusions exclusions;
private final CallGraph cg;
RDMap(BitVectorSolver<IBasicBlock> solver, OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h,
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) {
System.err.println("Init pointer Key mod ");
}
this.exclusions = exclusions;
this.cg = cg;
Map<PointerKey, MutableIntSet> pointerKeyMod = initPointerKeyMod(domain, node, h, pa);
if (VERBOSE) {
System.err.println("Eager populate");
@ -313,7 +317,7 @@ public class HeapReachingDefs {
HeapStatement.ReturnCaller r = (HeapStatement.ReturnCaller) s;
IBasicBlock bb = cfg.getBlockForInstruction(r.getCall());
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
return OrdinalSet.empty();
} else {
@ -364,19 +368,17 @@ public class HeapReachingDefs {
private static Map<Statement, OrdinalSet<Statement>> makeResult(BitVectorSolver<IBasicBlock> solver,
OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h, PointerAnalysis pa,
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
* being tracked by r?
*
* @param mod
*/
private static boolean allCalleesMod(ReturnCaller r, Map<CGNode, OrdinalSet<PointerKey>> mod) {
Collection<CGNode> targets = r.getNode().getPossibleTargets(r.getCall().getCallSite());
private static boolean allCalleesMod(CallGraph cg, ReturnCaller r, Map<CGNode, OrdinalSet<PointerKey>> mod) {
Collection<CGNode> targets = cg.getPossibleTargets(r.getNode(), r.getCall().getCallSite());
if (targets.isEmpty()) {
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.IClass;
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.propagation.PointerAnalysis;
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 DataDependenceOptions dOptions;
private final CallGraph cg;
/**
* @param mod
@ -109,12 +112,13 @@ public class PDG extends SlowSparseNumberedGraph<Statement> {
*/
public PDG(final CGNode node, PointerAnalysis pa, Map<CGNode, OrdinalSet<PointerKey>> mod,
Map<CGNode, OrdinalSet<PointerKey>> ref, DataDependenceOptions dOptions, ControlDependenceOptions cOptions,
HeapExclusions exclusions) {
HeapExclusions exclusions, CallGraph cg) {
super();
if (node == null) {
throw new IllegalArgumentException("node is null");
}
this.cg = cg;
this.node = node;
this.heapModel = pa == null ? null : new DelegatingExtendedHeapModel(pa.getHeapModel());
this.pa = pa;
@ -493,7 +497,7 @@ public class PDG extends SlowSparseNumberedGraph<Statement> {
Collection<Statement> relevantStatements = Iterator2Collection.toCollection(new FilterIterator<Statement>(iterator(), f));
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()) {
switch (st.getKind()) {
@ -829,13 +833,13 @@ public class PDG extends SlowSparseNumberedGraph<Statement> {
}
if (!dOptions.isIgnoreHeap()) {
OrdinalSet<PointerKey> uref = unionHeapLocations(node, call, ref);
OrdinalSet<PointerKey> uref = unionHeapLocations(cg, node, call, ref);
for (PointerKey p : uref) {
Statement st = new HeapStatement.ParamCaller(node, callIndex, p);
addNode(st);
params.add(st);
}
OrdinalSet<PointerKey> umod = unionHeapLocations(node, call, mod);
OrdinalSet<PointerKey> umod = unionHeapLocations(cg, node, call, mod);
for (PointerKey p : umod) {
Statement st = new HeapStatement.ReturnCaller(node, callIndex, p);
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.
*/
private OrdinalSet<PointerKey> unionHeapLocations(CGNode n, SSAAbstractInvokeInstruction call,
private OrdinalSet<PointerKey> unionHeapLocations(CallGraph cg, CGNode n, SSAAbstractInvokeInstruction call,
Map<CGNode, OrdinalSet<PointerKey>> loc) {
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());
}
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));
if (!dOptions.equals(DataDependenceOptions.NONE)) {
// 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);
addNode(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));
if (!dOptions.equals(DataDependenceOptions.NONE)) {
// 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);
addNode(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));
if (!dOptions.equals(DataDependenceOptions.NONE)) {
// 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())) {
Statement s = new HeapStatement.ReturnCallee(t, r.getLocation());
addNode(s);
@ -258,7 +258,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
// data dependence predecessors
for (Iterator<? extends CGNode> it = cg.getPredNodes(N.getNode()); it.hasNext();) {
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();
IR ir = caller.getIR();
IntSet indices = ir.getCallInstructionIndices(site);
@ -287,7 +287,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
// data dependence predecessors
for (Iterator<? extends CGNode> it = cg.getPredNodes(N.getNode()); it.hasNext();) {
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();
IR ir = caller.getIR();
IntSet indices = ir.getCallInstructionIndices(site);
@ -312,7 +312,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
if (!cOptions.equals(ControlDependenceOptions.NONE)) {
for (Iterator<? extends CGNode> it = cg.getPredNodes(N.getNode()); it.hasNext();) {
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();
IR ir = caller.getIR();
IntSet indices = ir.getCallInstructionIndices(site);
@ -346,7 +346,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
if (ns.getInstruction() instanceof SSAAbstractInvokeInstruction) {
HashSet<Statement> result = HashSetFactory.make();
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);
addNode(s);
result.add(s);
@ -371,7 +371,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
// data dependence predecessors
for (Iterator<? extends CGNode> it = cg.getPredNodes(N.getNode()); it.hasNext();) {
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();
IR ir = caller.getIR();
IntSet indices = ir.getCallInstructionIndices(site);
@ -393,7 +393,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
// data dependence predecessors
for (Iterator<? extends CGNode> it = cg.getPredNodes(N.getNode()); it.hasNext();) {
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();
IR ir = caller.getIR();
IntSet indices = ir.getCallInstructionIndices(site);
@ -416,7 +416,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
// data dependence predecessors
for (Iterator<? extends CGNode> it = cg.getPredNodes(N.getNode()); it.hasNext();) {
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();
IR ir = caller.getIR();
IntSet indices = ir.getCallInstructionIndices(site);
@ -437,7 +437,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
Collection<Statement> result = HashSetFactory.make(5);
if (!dOptions.equals(DataDependenceOptions.NONE)) {
// 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++) {
if (call.getUse(i) == pac.getValueNumber()) {
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);
if (!dOptions.equals(DataDependenceOptions.NONE)) {
// 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())) {
Statement s = new HeapStatement.ParamCallee(t, pc.getLocation());
addNode(s);
@ -480,7 +480,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
if (dst instanceof MethodEntryStatement) {
if (ns.getInstruction() instanceof SSAAbstractInvokeInstruction) {
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 {
return false;
}
@ -502,7 +502,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
}
if (dst.getKind().equals(Kind.EXC_RET_CALLER)) {
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 {
return false;
}
@ -513,7 +513,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
}
if (dst.getKind().equals(Kind.NORMAL_RET_CALLER)) {
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 {
return false;
}
@ -526,7 +526,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
HeapStatement.ReturnCaller r = (HeapStatement.ReturnCaller) dst;
HeapStatement h = (HeapStatement) src;
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 {
return false;
}
@ -540,7 +540,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
ParamStatement.ParamCaller caller = (ParamStatement.ParamCaller) src;
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 {
return false;
}
@ -554,7 +554,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
HeapStatement.ParamCaller caller = (HeapStatement.ParamCaller) src;
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 {
return false;
}
@ -618,7 +618,7 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
public PDG getPDG(CGNode node) {
PDG result = pdgMap.get(node);
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);
for (Iterator<? extends Statement> it = result.iterator(); it.hasNext();) {
nodeMgr.addNode(it.next());
@ -631,4 +631,8 @@ public class SDG extends AbstractNumberedGraph<Statement> implements ISDG {
return cOptions;
}
public CallGraph getCallGraph() {
return cg;
}
}