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() { predicate likelyReachable() {
start_bb_likely_reachable(this) 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) { private predicate start_bb_likely_reachable(BasicBlock b) {

View File

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