Python: Fix several bad join orders.

Performance on `taers232c/GAMADV-X` (which exhibited pathological behaviour in
the most recent dist upgrade) went from ~670s to ~313s on
`py/hardcoded-credentials`.

There are still a few tuple counts in the 10-100 million range, but this commit
takes care of all of the ones that numbered in the billions. (A single tuple
count in the 100-1000 million range remains, but it appears to be less critical,
taking only two seconds to calculate.)
This commit is contained in:
Taus Brock-Nannestad
2019-12-17 17:19:49 +01:00
parent 5cea452123
commit 1d94f6d303
2 changed files with 37 additions and 7 deletions

View File

@@ -50,8 +50,16 @@ class EssaVariable extends TEssaDefinition {
* Note that this differs from `EssaVariable.getAUse()`.
*/
ControlFlowNode getASourceUse() {
exists(SsaSourceVariable var |
result = use_for_var(var) and
result = var.getASourceUse()
)
}
pragma[nomagic]
private ControlFlowNode use_for_var(SsaSourceVariable var) {
result = this.getAUse() and
result = this.getSourceVariable().getASourceUse()
var = this.getSourceVariable()
}
/** Gets the scope of this variable. */
@@ -268,11 +276,16 @@ class PhiFunction extends EssaDefinition, TPhiFunction {
not exists(this.inputEdgeRefinement(result))
}
pragma[noinline]
private SsaSourceVariable pred_var(BasicBlock pred) {
result = this.getSourceVariable() and
pred = this.nonPiInput()
}
/** Gets another definition of the same source variable that reaches this definition. */
private EssaDefinition reachingDefinition(BasicBlock pred) {
result.getScope() = this.getScope() and
result.getSourceVariable() = this.getSourceVariable() and
pred = this.nonPiInput() and
result.getSourceVariable() = pred_var(pred) and
result.reachesEndOfBlock(pred)
}

View File

@@ -578,6 +578,13 @@ cached module PointsToInternal {
)
or
/* Undefined variable */
undefined_variable(def, context, value, origin)
or
/* Builtin not defined in outer scope */
builtin_not_in_outer_scope(def, context, value, origin)
}
private predicate undefined_variable(ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
exists(Scope scope |
not def.getVariable().getName() = "__name__" and
not def.getVariable().isMetaVariable() and
@@ -587,8 +594,9 @@ cached module PointsToInternal {
def.getSourceVariable() instanceof LocalVariable and (context.isImport() or context.isRuntime() or context.isMain())
) and
value = ObjectInternal::undefined() and origin = def.getDefiningNode()
or
/* Builtin not defined in outer scope */
}
private predicate builtin_not_in_outer_scope(ScopeEntryDefinition def, PointsToContext context, ObjectInternal value, ControlFlowNode origin) {
exists(Module mod, GlobalVariable var |
var = def.getSourceVariable() and
mod = def.getScope().getEnclosingModule() and
@@ -1113,8 +1121,17 @@ module InterProceduralPointsTo {
* Transfer of values from the callsite to the callee, for enclosing variables, but not arguments/parameters. */
pragma [noinline]
private predicate callsite_entry_value_transfer(EssaVariable caller_var, PointsToContext caller, ScopeEntryDefinition entry_def, PointsToContext callee) {
entry_def.getSourceVariable() = caller_var.getSourceVariable() and
callsite_calls_function(caller_var.getAUse(), caller, entry_def.getScope(), callee, _)
exists(ControlFlowNode use, SsaSourceVariable var |
var_and_use(caller_var, use, var) and
entry_def.getSourceVariable() = var and
callsite_calls_function(use, caller, entry_def.getScope(), callee, _)
)
}
pragma[nomagic]
private predicate var_and_use(EssaVariable caller_var, ControlFlowNode use, SsaSourceVariable var) {
use = caller_var.getAUse() and
var = caller_var.getSourceVariable()
}
/** Helper for `scope_entry_value_transfer`. */