Add new callbacks for tracking exploded supergraph

A subclass of TabulationSolver can now override the methods
newNormalExplodedEdge(), newCallExplodedEdge(), and
newReturnExplodedEdge() to take some action whenever (logically)
some edge in the exploded supergraph is "discovered" during
tabulation.
This commit is contained in:
Manu Sridharan 2016-07-22 11:16:05 -07:00
parent 3156f03145
commit b761e3871b
2 changed files with 65 additions and 10 deletions

View File

@ -61,6 +61,7 @@ public class PartiallyBalancedTabulationSolver<T, P, F> extends TabulationSolver
T fakeEntry = problem.getFakeEntry(retSite);
PathEdge<T> seed = PathEdge.createPathEdge(fakeEntry, d3, retSite, d3);
addSeed(seed);
newReturnExplodedEdge(n, j, retSite, d3);
}
}
} else {

View File

@ -344,7 +344,9 @@ public class TabulationSolver<T, P, F> {
D3.foreach(new IntSetAction() {
@Override
public void act(int d3) {
propagate(edge.entry, edge.d1, m, d3);
if (propagate(edge.entry, edge.d1, m, d3)) {
newNormalExplodedEdge(edge.target, edge.d2, m, d3);
}
}
});
}
@ -435,7 +437,7 @@ public class TabulationSolver<T, P, F> {
IntSetAction action = new IntSetAction() {
@Override
public void act(final int d4) {
propToReturnSite(c, entries, retSite, d4, D5);
propToReturnSite(c, entries, retSite, d4, D5, edge);
}
};
D4.foreach(action);
@ -461,7 +463,7 @@ public class TabulationSolver<T, P, F> {
@Override
public void act(final int d4) {
final IntSet D5 = computeBinaryFlow(d4, edge.d2, (IBinaryReturnFlowFunction) retf);
propToReturnSite(c, entries, retSite, d4, D5);
propToReturnSite(c, entries, retSite, d4, D5, edge);
}
});
@ -476,8 +478,9 @@ public class TabulationSolver<T, P, F> {
* @param d4 a fact s.t. <c, d4> -> <callee, d2> was recorded as call flow and <callee, d2> is the source of the summary edge
* being applied
* @param D5 facts to propagate to return site
* @param edge the path edge ending at the exit site of the callee
*/
private void propToReturnSite(final T c, final T[] entries, final T retSite, final int d4, final IntSet D5) {
private void propToReturnSite(final T c, final T[] entries, final T retSite, final int d4, final IntSet D5, final PathEdge<T> edge) {
if (D5 != null) {
D5.foreach(new IntSetAction() {
@Override
@ -505,7 +508,9 @@ public class TabulationSolver<T, P, F> {
public void act(int d3) {
// set curPathEdge to be consistent with its setting in processCall() when applying a summary edge
curPathEdge = PathEdge.createPathEdge(s_p, d3, c, d4);
propagate(s_p, d3, retSite, d5);
if (propagate(s_p, d3, retSite, d5)) {
newReturnExplodedEdge(edge.target, edge.d2, retSite, d5);
}
}
});
}
@ -569,7 +574,9 @@ public class TabulationSolver<T, P, F> {
D3.foreach(new IntSetAction() {
@Override
public void act(int d3) {
propagate(edge.entry, edge.d1, m, d3);
if (propagate(edge.entry, edge.d1, m, d3)) {
newNormalExplodedEdge(edge.target, edge.d2, m, d3);
}
}
});
}
@ -597,7 +604,9 @@ public class TabulationSolver<T, P, F> {
public void act(int x) {
assert x >= 0;
assert edge.d1 >= 0;
propagate(edge.entry, edge.d1, returnSite, x);
if (propagate(edge.entry, edge.d1, returnSite, x)) {
newNormalExplodedEdge(edge.target, edge.d2, returnSite, x);
}
}
});
}
@ -651,6 +660,7 @@ public class TabulationSolver<T, P, F> {
// we get reuse if we _don't_ propagate a new fact to the callee entry
final boolean gotReuse = !propagate(calleeEntry, d1, calleeEntry, d1);
recordCall(edge.target, calleeEntry, d1, gotReuse);
newCallExplodedEdge(edge.target, edge.d2, calleeEntry, d1);
// cache the fact that we've flowed <c, d2> -> <callee, d1> by a
// call flow
callFlow.addCallEdge(callNodeNum, edge.d2, d1);
@ -677,7 +687,7 @@ public class TabulationSolver<T, P, F> {
final IFlowFunction retf = flowFunctionMap.getReturnFlowFunction(edge.target, exit, returnSite);
reachedBySummary.foreach(new IntSetAction() {
@Override
public void act(int d2) {
public void act(final int d2) {
assert curSummaryEdge == null : "curSummaryEdge should be null here";
curSummaryEdge = PathEdge.createPathEdge(calleeEntry, d1, exit, d2);
if (retf instanceof IBinaryReturnFlowFunction) {
@ -686,7 +696,9 @@ public class TabulationSolver<T, P, F> {
D5.foreach(new IntSetAction() {
@Override
public void act(int d5) {
propagate(edge.entry, edge.d1, returnSite, d5);
if (propagate(edge.entry, edge.d1, returnSite, d5)) {
newReturnExplodedEdge(exit, d2, returnSite, d5);
}
}
});
}
@ -696,7 +708,9 @@ public class TabulationSolver<T, P, F> {
D5.foreach(new IntSetAction() {
@Override
public void act(int d5) {
propagate(edge.entry, edge.d1, returnSite, d5);
if (propagate(edge.entry, edge.d1, returnSite, d5)) {
newReturnExplodedEdge(exit, d2, returnSite, d5);
}
}
});
}
@ -1065,4 +1079,44 @@ public class TabulationSolver<T, P, F> {
protected PathEdge<T> getCurSummaryEdge() {
return curSummaryEdge;
}
/**
* Indicates that due to a path edge with destination <pred, d1> and a normal flow function application,
* a new path edge with destination <succ, d2> was created. To be overridden in subclasses. We also
* use this function to record call-to-return flow.
*
* @param pred
* @param d1
* @param succ
* @param d2
*/
protected void newNormalExplodedEdge(T pred, int d1, T succ, int d2) {
}
/**
* Indicates that due to a path edge with destination <caller, d1> and application of a call flow function,
* a new path edge with destination <calleeEntry, d2> was created. To be overridden in subclasses.
*
* @param caller
* @param d1
* @param calleeEntry
* @param d2
*/
protected void newCallExplodedEdge(T caller, int d1, T calleeEntry, int d2) {
}
/**
* Indicates that due to a path edge with destination <exit, d1> and application of a return flow function,
* a new path edge with destination <returnSite, d2> was created. To be overridden in subclasses.
*
* @param exit
* @param d1
* @param returnSite
* @param d2
*/
protected void newReturnExplodedEdge(T exit, int d1, T returnSite, int d2) {
}
}