some debug code
git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@2305 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
parent
497558d268
commit
eec4940c52
|
@ -60,13 +60,14 @@ import com.ibm.wala.util.intset.OrdinalSetMapping;
|
||||||
import com.ibm.wala.util.intset.SparseIntSet;
|
import com.ibm.wala.util.intset.SparseIntSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computation of reaching definitions for heap locations, relying on pointer
|
* Computation of reaching definitions for heap locations, relying on pointer analysis
|
||||||
* analysis
|
|
||||||
*
|
*
|
||||||
* @author sjfink
|
* @author sjfink
|
||||||
*/
|
*/
|
||||||
public class HeapReachingDefs {
|
public class HeapReachingDefs {
|
||||||
|
|
||||||
|
private static final boolean DEBUG = false;
|
||||||
|
|
||||||
private static final boolean VERBOSE = false;
|
private static final boolean VERBOSE = false;
|
||||||
|
|
||||||
private final ModRef modRef;
|
private final ModRef modRef;
|
||||||
|
@ -76,8 +77,7 @@ public class HeapReachingDefs {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For each statement s, return the set of statements that may def the heap
|
* For each statement s, return the set of statements that may def the heap value read by s.
|
||||||
* value read by s.
|
|
||||||
*
|
*
|
||||||
* @param node
|
* @param node
|
||||||
* the node we are computing heap reaching defs for
|
* the node we are computing heap reaching defs for
|
||||||
|
@ -86,13 +86,12 @@ public class HeapReachingDefs {
|
||||||
* @param pa
|
* @param pa
|
||||||
* governing pointer analysis
|
* governing pointer analysis
|
||||||
* @param mod
|
* @param mod
|
||||||
* the set of heap locations which may be written (transitively) by
|
* the set of heap locations which may be written (transitively) by this node. These are logically return
|
||||||
* this node. These are logically return values in the SDG.
|
* values in the SDG.
|
||||||
* @param statements
|
* @param statements
|
||||||
* the statements whose def-use are considered interesting
|
* the statements whose def-use are considered interesting
|
||||||
* @param exclusions
|
* @param exclusions
|
||||||
* heap locations that should be excluded from data dependence
|
* heap locations that should be excluded from data dependence tracking
|
||||||
* tracking
|
|
||||||
*
|
*
|
||||||
* @throws IllegalArgumentException
|
* @throws IllegalArgumentException
|
||||||
* if pa is null
|
* if pa is null
|
||||||
|
@ -108,11 +107,15 @@ public class HeapReachingDefs {
|
||||||
if (pa == null) {
|
if (pa == null) {
|
||||||
throw new IllegalArgumentException("pa is null");
|
throw new IllegalArgumentException("pa is null");
|
||||||
}
|
}
|
||||||
if (VERBOSE) {
|
if (VERBOSE | DEBUG) {
|
||||||
System.err.println("Reaching Defs " + node);
|
System.err.println("Reaching Defs " + node);
|
||||||
System.err.println(statements.size());
|
System.err.println(statements.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DEBUG) {
|
||||||
|
System.err.println(ir);
|
||||||
|
}
|
||||||
|
|
||||||
// create a control flow graph with one instruction per basic block.
|
// create a control flow graph with one instruction per basic block.
|
||||||
ExplodedControlFlowGraph cfg = ExplodedControlFlowGraph.make(ir);
|
ExplodedControlFlowGraph cfg = ExplodedControlFlowGraph.make(ir);
|
||||||
|
|
||||||
|
@ -124,8 +127,8 @@ public class HeapReachingDefs {
|
||||||
Map<Integer, NormalStatement> ssaInstructionIndex2Statement = mapInstructionsToStatements(domain);
|
Map<Integer, NormalStatement> ssaInstructionIndex2Statement = mapInstructionsToStatements(domain);
|
||||||
|
|
||||||
// solve reaching definitions as a dataflow problem
|
// solve reaching definitions as a dataflow problem
|
||||||
BitVectorFramework<ExplodedBasicBlock, Statement> rd = new BitVectorFramework<ExplodedBasicBlock, Statement>(cfg, new RD(node, cfg, pa,
|
BitVectorFramework<ExplodedBasicBlock, Statement> rd = new BitVectorFramework<ExplodedBasicBlock, Statement>(cfg, new RD(node,
|
||||||
domain, ssaInstructionIndex2Statement, exclusions), domain);
|
cfg, pa, domain, ssaInstructionIndex2Statement, exclusions), domain);
|
||||||
if (VERBOSE) {
|
if (VERBOSE) {
|
||||||
System.err.println("Solve ");
|
System.err.println("Solve ");
|
||||||
}
|
}
|
||||||
|
@ -285,8 +288,7 @@ public class HeapReachingDefs {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For a statement s, compute the set of statements that may def the heap
|
* For a statement s, compute the set of statements that may def the heap value read by s.
|
||||||
* value read by s.
|
|
||||||
*/
|
*/
|
||||||
OrdinalSet<Statement> computeResult(Statement s, Map<PointerKey, MutableIntSet> pointerKeyMod,
|
OrdinalSet<Statement> computeResult(Statement s, Map<PointerKey, MutableIntSet> pointerKeyMod,
|
||||||
BitVectorSolver<? extends ISSABasicBlock> solver, OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h,
|
BitVectorSolver<? extends ISSABasicBlock> solver, OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h,
|
||||||
|
@ -300,11 +302,13 @@ public class HeapReachingDefs {
|
||||||
ISSABasicBlock bb = cfg.getBlockForInstruction(n.getInstructionIndex());
|
ISSABasicBlock bb = cfg.getBlockForInstruction(n.getInstructionIndex());
|
||||||
BitVectorVariable v = solver.getIn(bb);
|
BitVectorVariable v = solver.getIn(bb);
|
||||||
MutableSparseIntSet defs = MutableSparseIntSet.makeEmpty();
|
MutableSparseIntSet defs = MutableSparseIntSet.makeEmpty();
|
||||||
|
if (v.getValue() != null) {
|
||||||
for (PointerKey p : ref) {
|
for (PointerKey p : ref) {
|
||||||
if (pointerKeyMod.get(p) != null) {
|
if (pointerKeyMod.get(p) != null) {
|
||||||
defs.addAll(pointerKeyMod.get(p).intersection(v.getValue()));
|
defs.addAll(pointerKeyMod.get(p).intersection(v.getValue()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return new OrdinalSet<Statement>(defs, domain);
|
return new OrdinalSet<Statement>(defs, domain);
|
||||||
} else {
|
} else {
|
||||||
return OrdinalSet.empty();
|
return OrdinalSet.empty();
|
||||||
|
@ -313,6 +317,9 @@ public class HeapReachingDefs {
|
||||||
HeapStatement.ReturnCallee r = (HeapStatement.ReturnCallee) s;
|
HeapStatement.ReturnCallee r = (HeapStatement.ReturnCallee) s;
|
||||||
PointerKey p = r.getLocation();
|
PointerKey p = r.getLocation();
|
||||||
BitVectorVariable v = solver.getIn(cfg.exit());
|
BitVectorVariable v = solver.getIn(cfg.exit());
|
||||||
|
if (DEBUG) {
|
||||||
|
System.err.println("computeResult " + cfg.exit() + " " + s + " " + pointerKeyMod.get(p) + " " + v);
|
||||||
|
}
|
||||||
if (pointerKeyMod.get(p) == null) {
|
if (pointerKeyMod.get(p) == null) {
|
||||||
return OrdinalSet.empty();
|
return OrdinalSet.empty();
|
||||||
}
|
}
|
||||||
|
@ -372,8 +379,7 @@ public class HeapReachingDefs {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For each statement s, compute the set of statements that may def the heap
|
* For each statement s, compute the set of statements that may def the heap value read by s.
|
||||||
* value read by s.
|
|
||||||
*/
|
*/
|
||||||
private Map<Statement, OrdinalSet<Statement>> makeResult(BitVectorSolver<? extends ISSABasicBlock> solver,
|
private Map<Statement, OrdinalSet<Statement>> makeResult(BitVectorSolver<? extends ISSABasicBlock> solver,
|
||||||
OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h, PointerAnalysis pa,
|
OrdinalSetMapping<Statement> domain, CGNode node, ExtendedHeapModel h, PointerAnalysis pa,
|
||||||
|
@ -384,8 +390,7 @@ public class HeapReachingDefs {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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?
|
|
||||||
*/
|
*/
|
||||||
private static boolean allCalleesMod(CallGraph cg, ReturnCaller r, Map<CGNode, OrdinalSet<PointerKey>> mod) {
|
private static boolean allCalleesMod(CallGraph cg, ReturnCaller r, Map<CGNode, OrdinalSet<PointerKey>> mod) {
|
||||||
Collection<CGNode> targets = cg.getPossibleTargets(r.getNode(), r.getCall().getCallSite());
|
Collection<CGNode> targets = cg.getPossibleTargets(r.getNode(), r.getCall().getCallSite());
|
||||||
|
@ -400,8 +405,7 @@ public class HeapReachingDefs {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<PointerKey> getMod(Statement s, CGNode n, ExtendedHeapModel h, PointerAnalysis pa,
|
private Collection<PointerKey> getMod(Statement s, CGNode n, ExtendedHeapModel h, PointerAnalysis pa, HeapExclusions exclusions) {
|
||||||
HeapExclusions exclusions) {
|
|
||||||
switch (s.getKind()) {
|
switch (s.getKind()) {
|
||||||
case NORMAL:
|
case NORMAL:
|
||||||
NormalStatement ns = (NormalStatement) s;
|
NormalStatement ns = (NormalStatement) s;
|
||||||
|
@ -470,9 +474,8 @@ public class HeapReachingDefs {
|
||||||
private final HeapExclusions exclusions;
|
private final HeapExclusions exclusions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* if (i,j) \in heapReturnCaller, then statement j is a
|
* if (i,j) \in heapReturnCaller, then statement j is a HeapStatement.ReturnCaller for statement i, a
|
||||||
* HeapStatement.ReturnCaller for statement i, a NormalStatement
|
* NormalStatement representing an invoke
|
||||||
* representing an invoke
|
|
||||||
*/
|
*/
|
||||||
private final IBinaryNaturalRelation heapReturnCaller = new BasicNaturalRelation();
|
private final IBinaryNaturalRelation heapReturnCaller = new BasicNaturalRelation();
|
||||||
|
|
||||||
|
@ -491,6 +494,9 @@ public class HeapReachingDefs {
|
||||||
private void initHeapReturnCaller() {
|
private void initHeapReturnCaller() {
|
||||||
for (Statement s : domain) {
|
for (Statement s : domain) {
|
||||||
if (s.getKind().equals(Kind.HEAP_RET_CALLER)) {
|
if (s.getKind().equals(Kind.HEAP_RET_CALLER)) {
|
||||||
|
if (DEBUG) {
|
||||||
|
System.err.println("initHeapReturnCaller " + s);
|
||||||
|
}
|
||||||
HeapStatement.ReturnCaller r = (ReturnCaller) s;
|
HeapStatement.ReturnCaller r = (ReturnCaller) s;
|
||||||
NormalStatement call = ssaInstructionIndex2Statement.get(r.getCallIndex());
|
NormalStatement call = ssaInstructionIndex2Statement.get(r.getCallIndex());
|
||||||
int i = domain.getMappedIndex(call);
|
int i = domain.getMappedIndex(call);
|
||||||
|
@ -501,15 +507,34 @@ public class HeapReachingDefs {
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnaryOperator<BitVectorVariable> getEdgeTransferFunction(ExplodedBasicBlock src, ExplodedBasicBlock dst) {
|
public UnaryOperator<BitVectorVariable> getEdgeTransferFunction(ExplodedBasicBlock src, ExplodedBasicBlock dst) {
|
||||||
|
if (DEBUG) {
|
||||||
|
System.err.println("getEdgeXfer: " + src + " " + dst + " " + src.isEntryBlock());
|
||||||
|
}
|
||||||
|
IntSet gen = null;
|
||||||
|
if (src.isEntryBlock()) {
|
||||||
|
if (DEBUG) {
|
||||||
|
System.err.println("heapEntry " + heapEntryStatements());
|
||||||
|
}
|
||||||
|
gen = new BitVectorIntSet(heapEntryStatements()).toSparseIntSet();
|
||||||
|
} else {
|
||||||
|
gen = new SparseIntSet();
|
||||||
|
}
|
||||||
if (src.getInstruction() != null && !(src.getInstruction() instanceof SSAAbstractInvokeInstruction)
|
if (src.getInstruction() != null && !(src.getInstruction() instanceof SSAAbstractInvokeInstruction)
|
||||||
&& !cfg.getNormalSuccessors(src).contains(dst)) {
|
&& !cfg.getNormalSuccessors(src).contains(dst)) {
|
||||||
// if the edge only happens due to exceptional control flow, then no
|
// if the edge only happens due to exceptional control flow, then no
|
||||||
// heap locations
|
// heap locations
|
||||||
// are def'ed or used
|
// are def'ed or used
|
||||||
|
if (DEBUG) {
|
||||||
|
System.err.println("Identity");
|
||||||
|
}
|
||||||
return BitVectorIdentity.instance();
|
return BitVectorIdentity.instance();
|
||||||
} else {
|
} else {
|
||||||
BitVector kill = kill(src);
|
BitVector kill = kill(src);
|
||||||
IntSet gen = gen(src);
|
IntSet gen2 = gen(src);
|
||||||
|
gen = gen2 == null ? gen : gen.union(gen2);
|
||||||
|
if (DEBUG) {
|
||||||
|
System.err.println("gen: " + gen + " kill: " + kill);
|
||||||
|
}
|
||||||
if (kill == null) {
|
if (kill == null) {
|
||||||
if (gen == null) {
|
if (gen == null) {
|
||||||
return BitVectorIdentity.instance();
|
return BitVectorIdentity.instance();
|
||||||
|
@ -531,7 +556,6 @@ public class HeapReachingDefs {
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnaryOperator<BitVectorVariable> getNodeTransferFunction(ExplodedBasicBlock node) {
|
public UnaryOperator<BitVectorVariable> getNodeTransferFunction(ExplodedBasicBlock node) {
|
||||||
Assertions.UNREACHABLE();
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,14 +568,14 @@ public class HeapReachingDefs {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return int set representing the heap def statements that are gen'ed by
|
* @return int set representing the heap def statements that are gen'ed by the basic block. null if none.
|
||||||
* the basic block. null if none.
|
|
||||||
*/
|
*/
|
||||||
IntSet gen(ExplodedBasicBlock b) {
|
IntSet gen(ExplodedBasicBlock b) {
|
||||||
if (b.isEntryBlock()) {
|
|
||||||
return heapEntryStatements();
|
|
||||||
} else {
|
|
||||||
SSAInstruction s = b.getInstruction();
|
SSAInstruction s = b.getInstruction();
|
||||||
|
if (DEBUG) {
|
||||||
|
System.err.println("gen " + b + " " + s);
|
||||||
|
}
|
||||||
if (s == null) {
|
if (s == null) {
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
|
@ -565,6 +589,9 @@ public class HeapReachingDefs {
|
||||||
}
|
}
|
||||||
int domainIndex = domain.getMappedIndex(st);
|
int domainIndex = domain.getMappedIndex(st);
|
||||||
assert (domainIndex != -1);
|
assert (domainIndex != -1);
|
||||||
|
if (DEBUG) {
|
||||||
|
System.err.println("GEN FOR " + s + " " + heapReturnCaller.getRelated(domainIndex));
|
||||||
|
}
|
||||||
return heapReturnCaller.getRelated(domainIndex);
|
return heapReturnCaller.getRelated(domainIndex);
|
||||||
} else {
|
} else {
|
||||||
Collection<PointerKey> gen = modRef.getMod(node, h, pa, s, exclusions);
|
Collection<PointerKey> gen = modRef.getMod(node, h, pa, s, exclusions);
|
||||||
|
@ -577,11 +604,9 @@ public class HeapReachingDefs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return int set representing all HEAP_PARAM_CALLEE statements in the
|
* @return int set representing all HEAP_PARAM_CALLEE statements in the domain.
|
||||||
* domain.
|
|
||||||
*/
|
*/
|
||||||
private IntSet heapEntryStatements() {
|
private IntSet heapEntryStatements() {
|
||||||
BitVectorIntSet result = new BitVectorIntSet();
|
BitVectorIntSet result = new BitVectorIntSet();
|
||||||
|
@ -594,8 +619,7 @@ public class HeapReachingDefs {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return int set representing the heap def statements that are killed by
|
* @return int set representing the heap def statements that are killed by the basic block. null if none.
|
||||||
* the basic block. null if none.
|
|
||||||
*/
|
*/
|
||||||
BitVector kill(ExplodedBasicBlock b) {
|
BitVector kill(ExplodedBasicBlock b) {
|
||||||
SSAInstruction s = b.getInstruction();
|
SSAInstruction s = b.getInstruction();
|
||||||
|
|
Loading…
Reference in New Issue