Skip to content

Commit e265259

Browse files
committed
Python: Change perf fix PoorMansFunctionResolution
Thanks @yoff, this leaves us with the following evaluation, which looks very close to the one in the other fix (but with cleaner implementation) -- both at 688k max tuples (although numbers are not exactly the same). ``` [2021-11-24 13:48:40] (14s) Tuple counts for PoorMansFunctionResolution::getSimpleMethodReferenceWithinClass#ff/2@e5f05asv after 74ms: 47493 ~3% {3} r1 = JOIN Class::Class::getAMethod_dispred#ff WITH py_Classes ON FIRST 1 OUTPUT Lhs.1, 0, Lhs.0 47335 ~0% {2} r2 = JOIN r1 WITH AstGenerated::Function_::getArg_dispred#fff ON FIRST 2 OUTPUT Rhs.2, Lhs.2 46683 ~0% {2} r3 = JOIN r2 WITH DataFlowPublic::ParameterNode::getParameter_dispred#fb_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1 259968 ~4% {2} r4 = JOIN r3 WITH LocalSources::Cached::hasLocalSource#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1 161985 ~0% {3} r5 = JOIN r4 WITH Attributes::AttrRef::accesses_dispred#bff_102#join_rhs ON FIRST 1 OUTPUT Rhs.1 'result', Lhs.1, Rhs.2 161985 ~2% {3} r6 = JOIN r5 WITH Attributes::AttrRead#class#f ON FIRST 1 OUTPUT Lhs.2, Lhs.1, Lhs.0 'result' 688766 ~0% {3} r7 = JOIN r6 WITH Function::Function::getName_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.1, Rhs.1 'func', Lhs.2 'result' 20928 ~0% {2} r8 = JOIN r7 WITH Class::Class::getAMethod_dispred#ff ON FIRST 2 OUTPUT Lhs.1 'func', Lhs.2 'result' return r8 ```
1 parent 47448d9 commit e265259

File tree

1 file changed

+6
-36
lines changed

1 file changed

+6
-36
lines changed

python/ql/lib/semmle/python/frameworks/internal/PoorMansFunctionResolution.qll

+6-36
Original file line numberDiff line numberDiff line change
@@ -62,49 +62,19 @@ private DataFlow::TypeTrackingNode poorMansFunctionTracker(DataFlow::TypeTracker
6262
exists(DataFlow::TypeTracker t2 | result = poorMansFunctionTracker(t2, func).track(t2, t))
6363
}
6464

65-
/** Helper predicate to avoid bad join order. */
66-
pragma[noinline]
67-
private predicate getSimpleMethodReferenceWithinClass_helper(
68-
Function func, Class cls, DataFlow::AttrRead read
69-
) {
70-
DataFlow::parameterNode(func.getArg(0)).flowsTo(read.getObject()) and
71-
cls.getAMethod() = func
72-
}
73-
74-
/**
75-
* Helper predicate to avoid bad join order, which looked like:
76-
*
77-
* (8s) Tuple counts for PoorMansFunctionResolution::getSimpleMethodReferenceWithinClass#ff/2@cbddf257 after 8.6s:
78-
* 387565 ~0% {3} r1 = JOIN Attributes::AttrRead#class#f WITH Attributes::AttrRef::accesses_dispred#bff ON FIRST 1 OUTPUT Rhs.2, Lhs.0 'result', Rhs.1
79-
* 6548632 ~0% {3} r2 = JOIN r1 WITH Function::Function::getName_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1 'func', Lhs.1 'result', Lhs.2
80-
* 5640480 ~0% {4} r3 = JOIN r2 WITH Class::Class::getAMethod_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'result', Lhs.2, Lhs.0 'func'
81-
* 55660458 ~0% {5} r4 = JOIN r3 WITH Class::Class::getAMethod_dispred#ff ON FIRST 1 OUTPUT Rhs.1, 0, Lhs.1 'result', Lhs.2, Lhs.3 'func'
82-
* 55621412 ~0% {4} r5 = JOIN r4 WITH AstGenerated::Function_::getArg_dispred#fff ON FIRST 2 OUTPUT Rhs.2, Lhs.2 'result', Lhs.3, Lhs.4 'func'
83-
* 54467144 ~0% {4} r6 = JOIN r5 WITH DataFlowPublic::ParameterNode::getParameter_dispred#fb_10#join_rhs ON FIRST 1 OUTPUT Lhs.2, Rhs.1, Lhs.1 'result', Lhs.3 'func'
84-
* 20928 ~0% {2} r7 = JOIN r6 WITH LocalSources::Cached::hasLocalSource#ff ON FIRST 2 OUTPUT Lhs.3 'func', Lhs.2 'result'
85-
* return r7
86-
*/
87-
pragma[noinline]
88-
private predicate getSimpleMethodReferenceWithinClass_helper2(
89-
Function func, Class cls, DataFlow::AttrRead read, Function readFunction
90-
) {
91-
getSimpleMethodReferenceWithinClass_helper(pragma[only_bind_into](func),
92-
pragma[only_bind_into](cls), pragma[only_bind_into](read)) and
93-
read.getAttributeName() = readFunction.getName()
94-
}
95-
9665
/**
9766
* Gets a reference to `func`. `func` must be defined inside a class, and the reference
9867
* will be inside a different method of the same class.
9968
*/
10069
private DataFlow::Node getSimpleMethodReferenceWithinClass(Function func) {
10170
// TODO: Should take MRO into account
102-
exists(Class cls, Function otherFunc |
103-
cls.getAMethod() = func and
104-
cls.getAMethod() = otherFunc
71+
exists(Class cls, Function otherFunc, DataFlow::Node selfRefOtherFunc |
72+
pragma[only_bind_into](cls).getAMethod() = func and
73+
pragma[only_bind_into](cls).getAMethod() = otherFunc
10574
|
106-
getSimpleMethodReferenceWithinClass_helper2(pragma[only_bind_into](otherFunc),
107-
pragma[only_bind_into](cls), pragma[only_bind_into](result), pragma[only_bind_into](func))
75+
selfRefOtherFunc.getALocalSource().(DataFlow::ParameterNode).getParameter() =
76+
otherFunc.getArg(0) and
77+
result.(DataFlow::AttrRead).accesses(selfRefOtherFunc, func.getName())
10878
)
10979
}
11080

0 commit comments

Comments
 (0)