optimizations in global data flow

This commit is contained in:
Erik Krogh Kristensen
2021-11-19 11:15:59 +01:00
parent f39872e649
commit c369b28a2a

View File

@@ -939,18 +939,21 @@ private predicate basicFlowStepNoBarrier(
* This predicate is field insensitive (it does not distinguish between `x` and `x.p`)
* and hence should only be used for purposes of approximation.
*/
pragma[inline]
pragma[noinline]
private predicate exploratoryFlowStep(
DataFlow::Node pred, DataFlow::Node succ, DataFlow::Configuration cfg
) {
basicFlowStepNoBarrier(pred, succ, _, cfg) or
exploratoryLoadStep(pred, succ, cfg) or
isAdditionalLoadStoreStep(pred, succ, _, _, cfg) or
// the following three disjuncts taken together over-approximate flow through
// higher-order calls
exploratoryCallbackStep(pred, succ) or
succ = pred.(DataFlow::FunctionNode).getAParameter() or
exploratoryBoundInvokeStep(pred, succ)
isRelevantForward(pred, cfg) and
(
basicFlowStepNoBarrier(pred, succ, _, cfg) or
exploratoryLoadStep(pred, succ, cfg) or
isAdditionalLoadStoreStep(pred, succ, _, _, cfg) or
// the following three disjuncts taken together over-approximate flow through
// higher-order calls
exploratoryCallbackStep(pred, succ) or
succ = pred.(DataFlow::FunctionNode).getAParameter() or
exploratoryBoundInvokeStep(pred, succ)
)
}
/**
@@ -1024,6 +1027,7 @@ private string getAPropertyUsedInLoadStore(DataFlow::Configuration cfg) {
* Holds if there exists a store-step from `pred` to `succ` under configuration `cfg`,
* and somewhere in the program there exists a load-step that could possibly read the stored value.
*/
pragma[noinline]
private predicate exploratoryForwardStoreStep(
DataFlow::Node pred, DataFlow::Node succ, DataFlow::Configuration cfg
) {
@@ -1075,8 +1079,10 @@ private string getABackwardsRelevantStoreProperty(DataFlow::Configuration cfg) {
private predicate isRelevantForward(DataFlow::Node nd, DataFlow::Configuration cfg) {
isSource(nd, cfg, _) and isLive()
or
exists(DataFlow::Node mid | isRelevantForward(mid, cfg) |
exploratoryFlowStep(mid, nd, cfg) or
exists(DataFlow::Node mid |
exploratoryFlowStep(mid, nd, cfg)
or
isRelevantForward(mid, cfg) and
exploratoryForwardStoreStep(mid, nd, cfg)
)
}
@@ -1098,11 +1104,10 @@ private predicate isRelevant(DataFlow::Node nd, DataFlow::Configuration cfg) {
private predicate isRelevantBackStep(
DataFlow::Node mid, DataFlow::Node nd, DataFlow::Configuration cfg
) {
exploratoryFlowStep(nd, mid, cfg)
or
isRelevantForward(nd, cfg) and
(
exploratoryFlowStep(nd, mid, cfg) or
exploratoryBackwardStoreStep(nd, mid, cfg)
)
exploratoryBackwardStoreStep(nd, mid, cfg)
}
/**
@@ -1273,23 +1278,30 @@ private predicate parameterPropRead(
DataFlow::Node arg, string prop, DataFlow::Node succ, DataFlow::Configuration cfg,
PathSummary summary
) {
exists(Function f, DataFlow::Node read, DataFlow::Node invk |
exists(Function f, DataFlow::Node read, DataFlow::Node invk, DataFlow::Node parm |
reachesReturn(f, read, cfg, summary) and
parameterPropReadStep(parm, read, prop, cfg, arg, invk, f, succ)
)
}
// all the non-recursive parts of parameterPropRead outlined into a precomputed predicate
pragma[noinline]
private predicate parameterPropReadStep(
DataFlow::SourceNode parm, DataFlow::Node read, string prop, DataFlow::Configuration cfg,
DataFlow::Node arg, DataFlow::Node invk, Function f, DataFlow::Node succ
) {
(
not f.isAsyncOrGenerator() and invk = succ
or
// load from an immediately awaited function call
f.isAsync() and
invk = getAwaitOperand(succ)
|
exists(DataFlow::SourceNode parm |
callInputStep(f, invk, arg, parm, cfg) and
(
reachesReturn(f, read, cfg, summary) and
read = parm.getAPropertyRead(prop)
or
reachesReturn(f, read, cfg, summary) and
exists(DataFlow::Node use | parm.flowsTo(use) | isAdditionalLoadStep(use, read, prop, cfg))
)
)
) and
callInputStep(f, invk, arg, parm, cfg) and
(
read = parm.getAPropertyRead(prop)
or
exists(DataFlow::Node use | parm.flowsTo(use) | isAdditionalLoadStep(use, read, prop, cfg))
)
}