Merge pull request #969 from markshannon/python-points-to-speed-up

Python: Refactor three predicates to improve join-order.
This commit is contained in:
Taus
2019-02-22 15:27:02 +01:00
committed by GitHub
2 changed files with 37 additions and 12 deletions

View File

@@ -1023,6 +1023,20 @@ class BasicBlock extends @py_flow_node {
predicate likelyReachable() {
start_bb_likely_reachable(this)
}
/** Gets the `ConditionBlock`, if any, that controls this block and
* does not control any other `ConditionBlock`s that control this block.
* That is the `ConditionBlock` that is closest dominator.
*/
ConditionBlock getImmediatelyControllingBlock() {
result = this.nonControllingImmediateDominator*().getImmediateDominator()
}
private BasicBlock nonControllingImmediateDominator() {
result = this.getImmediateDominator() and
not result.(ConditionBlock).controls(this, _)
}
}
private predicate start_bb_likely_reachable(BasicBlock b) {

View File

@@ -447,10 +447,13 @@ module PointsTo {
private module Layer {
/* Holds if BasicBlock `b` is reachable, given the context `context`. */
predicate reachableBlock(BasicBlock b, PointsToContext context) {
context.appliesToScope(b.getScope()) and
forall(ConditionBlock guard |
guard.controls(b, _) |
predicate reachableBlock(BasicBlock b, PointsToContext context) {
context.appliesToScope(b.getScope()) and not exists(ConditionBlock guard | guard.controls(b, _))
or
exists(ConditionBlock guard |
guard = b.getImmediatelyControllingBlock() and
reachableBlock(guard, context)
|
exists(Object value |
points_to(guard.getLastNode(), context, value, _, _)
|
@@ -1827,21 +1830,27 @@ module PointsTo {
)
}
pragma [noinline]
private predicate callsite_points_to_python(CallsiteRefinement def, PointsToContext context, Object value, ClassObject cls, CfgOrigin origin) {
ssa_variable_points_to(def.getInput(), context, value, cls, origin) and
exists(CallNode call, PythonSsaSourceVariable var |
/** Holds if `call`, in `context` is a call to a function that does not modify the refined variable */
private predicate call_to_safe_function(CallsiteRefinement def, PointsToContext context) {
exists(CallNode call |
call = def.getCall() and
var = def.getSourceVariable() and
context.untrackableCall(call) and
exists(PyFunctionObject modifier, Function f |
f = modifier.getFunction() and
call = get_a_call(modifier, context) and
not modifies_escaping_variable(f, var)
not modifies_escaping_variable(f, def.getSourceVariable())
)
)
}
private predicate callsite_points_to_python(CallsiteRefinement def, PointsToContext context, Object value, ClassObject cls, CfgOrigin origin) {
exists(EssaVariable input |
input = def.getInput() and
ssa_variable_points_to(input, context, value, cls, origin) and
call_to_safe_function(def, context)
)
}
private predicate modifies_escaping_variable(Function modifier, PythonSsaSourceVariable var) {
exists(var.redefinedAtCallSite()) and
modifier.getBody().contains(var.(Variable).getAStore())
@@ -2987,19 +2996,21 @@ class SuperBoundMethod extends Object {
SuperCall superObject;
string name;
ClassObject startType;
cached
SuperBoundMethod() {
exists(ControlFlowNode object |
this.(AttrNode).getObject(name) = object |
PointsTo::points_to(object, _, superObject, _, _)
PointsTo::points_to(object, _, superObject, _, _) and
startType = superObject.startType()
)
}
FunctionObject getFunction(PointsToContext ctx) {
exists(ClassList mro |
mro = PointsTo::Types::get_mro(superObject.selfType(ctx)) |
result = mro.startingAt(superObject.startType()).getTail().lookup(name)
result = mro.startingAt(startType).getTail().lookup(name)
)
}