mirror of
https://github.com/github/codeql.git
synced 2026-05-02 12:15:17 +02:00
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
```
This commit is contained in:
@@ -62,49 +62,19 @@ private DataFlow::TypeTrackingNode poorMansFunctionTracker(DataFlow::TypeTracker
|
||||
exists(DataFlow::TypeTracker t2 | result = poorMansFunctionTracker(t2, func).track(t2, t))
|
||||
}
|
||||
|
||||
/** Helper predicate to avoid bad join order. */
|
||||
pragma[noinline]
|
||||
private predicate getSimpleMethodReferenceWithinClass_helper(
|
||||
Function func, Class cls, DataFlow::AttrRead read
|
||||
) {
|
||||
DataFlow::parameterNode(func.getArg(0)).flowsTo(read.getObject()) and
|
||||
cls.getAMethod() = func
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper predicate to avoid bad join order, which looked like:
|
||||
*
|
||||
* (8s) Tuple counts for PoorMansFunctionResolution::getSimpleMethodReferenceWithinClass#ff/2@cbddf257 after 8.6s:
|
||||
* 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
|
||||
* 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
|
||||
* 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'
|
||||
* 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'
|
||||
* 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'
|
||||
* 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'
|
||||
* 20928 ~0% {2} r7 = JOIN r6 WITH LocalSources::Cached::hasLocalSource#ff ON FIRST 2 OUTPUT Lhs.3 'func', Lhs.2 'result'
|
||||
* return r7
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate getSimpleMethodReferenceWithinClass_helper2(
|
||||
Function func, Class cls, DataFlow::AttrRead read, Function readFunction
|
||||
) {
|
||||
getSimpleMethodReferenceWithinClass_helper(pragma[only_bind_into](func),
|
||||
pragma[only_bind_into](cls), pragma[only_bind_into](read)) and
|
||||
read.getAttributeName() = readFunction.getName()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a reference to `func`. `func` must be defined inside a class, and the reference
|
||||
* will be inside a different method of the same class.
|
||||
*/
|
||||
private DataFlow::Node getSimpleMethodReferenceWithinClass(Function func) {
|
||||
// TODO: Should take MRO into account
|
||||
exists(Class cls, Function otherFunc |
|
||||
cls.getAMethod() = func and
|
||||
cls.getAMethod() = otherFunc
|
||||
exists(Class cls, Function otherFunc, DataFlow::Node selfRefOtherFunc |
|
||||
pragma[only_bind_into](cls).getAMethod() = func and
|
||||
pragma[only_bind_into](cls).getAMethod() = otherFunc
|
||||
|
|
||||
getSimpleMethodReferenceWithinClass_helper2(pragma[only_bind_into](otherFunc),
|
||||
pragma[only_bind_into](cls), pragma[only_bind_into](result), pragma[only_bind_into](func))
|
||||
selfRefOtherFunc.getALocalSource().(DataFlow::ParameterNode).getParameter() =
|
||||
otherFunc.getArg(0) and
|
||||
result.(DataFlow::AttrRead).accesses(selfRefOtherFunc, func.getName())
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user