mirror of
https://github.com/github/codeql.git
synced 2026-04-29 18:55:14 +02:00
Python: Fix bad join order in py/ineffectual-statement.
This used to take 30s on `cpython`.
```
Tuple counts for StatementNoEffect::side_effecting_binary#f:
46522 ~0% {2} r1 = ClassObject::ClassObject::hasAttribute_dispred#fb AS L AND NOT StatementNoEffect::side_effecting_binary#f#antijoin_rhs AS R(L.<0>, L.<1>)
46522 ~2% {2} r2 = SCAN r1 OUTPUT r1.<1>, r1.<0>
950960 ~2% {2} r3 = JOIN r2 WITH Operations::Operator::getSpecialMethodName_dispred#ff_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1>, r2.<1>
950960 ~2% {2} r4 = JOIN r3 WITH py_operators AS R ON FIRST 1 OUTPUT R.<2>, r3.<1>
950960 ~0% {3} r5 = JOIN r4 WITH AstGenerated::BinaryExpr_::getLeft_dispred#ff AS R ON FIRST 1 OUTPUT R.<1>, r4.<1>, r4.<0>
122934382 ~0% {2} r6 = JOIN r2 WITH Operations::Cmpop::getSpecialMethodName_dispred#ff_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1>, r2.<1>
122934382 ~3% {3} r7 = JOIN r6 WITH project#Operations::Compare::compares_dispred#ffff#3_201#join_rhs AS R ON FIRST 1 OUTPUT R.<2>, r6.<1>, R.<1>
123885342 ~3% {3} r8 = r5 \/ r7
300 ~8% {1} r9 = JOIN r8 WITH project#Exprs::Expr::refersTo_dispred#ffff AS R ON FIRST 2 OUTPUT r8.<2>
return r9
```
With this commit, it takes a few milliseconds.
This commit is contained in:
@@ -49,28 +49,45 @@ predicate side_effecting_descriptor_type(ClassObject descriptor) {
|
||||
* side-effecting unless we know otherwise.
|
||||
*/
|
||||
predicate side_effecting_binary(Expr b) {
|
||||
exists(Expr sub, string method_name |
|
||||
sub = b.(BinaryExpr).getLeft() and
|
||||
method_name = b.(BinaryExpr).getOp().getSpecialMethodName()
|
||||
exists(Expr sub, ClassObject cls, string method_name |
|
||||
binary_operator_special_method(b, sub, cls, method_name)
|
||||
or
|
||||
exists(Cmpop op |
|
||||
b.(Compare).compares(sub, op, _) and
|
||||
method_name = op.getSpecialMethodName()
|
||||
)
|
||||
comparison_special_method(b, sub, cls, method_name)
|
||||
|
|
||||
exists(ClassObject cls |
|
||||
sub.refersTo(_, cls, _) and
|
||||
cls.hasAttribute(method_name)
|
||||
and
|
||||
not exists(ClassObject declaring |
|
||||
declaring.declaresAttribute(method_name)
|
||||
and declaring = cls.getAnImproperSuperType() and
|
||||
declaring.isBuiltin() and not declaring = theObjectType()
|
||||
)
|
||||
method_name = special_method() and
|
||||
cls.hasAttribute(method_name)
|
||||
and
|
||||
not exists(ClassObject declaring |
|
||||
declaring.declaresAttribute(method_name)
|
||||
and declaring = cls.getAnImproperSuperType() and
|
||||
declaring.isBuiltin() and not declaring = theObjectType()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate binary_operator_special_method(BinaryExpr b, Expr sub, ClassObject cls, string method_name) {
|
||||
method_name = special_method() and
|
||||
sub = b.getLeft() and
|
||||
method_name = b.getOp().getSpecialMethodName() and
|
||||
sub.refersTo(_, cls, _)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate comparison_special_method(Compare b, Expr sub, ClassObject cls, string method_name) {
|
||||
exists(Cmpop op |
|
||||
b.compares(sub, op, _) and
|
||||
method_name = op.getSpecialMethodName()
|
||||
) and
|
||||
sub.refersTo(_, cls, _)
|
||||
}
|
||||
|
||||
private string special_method() {
|
||||
result = any(Cmpop c).getSpecialMethodName()
|
||||
or
|
||||
result = any(BinaryExpr b).getOp().getSpecialMethodName()
|
||||
}
|
||||
|
||||
predicate is_notebook(File f) {
|
||||
exists(Comment c |
|
||||
c.getLocation().getFile() = f |
|
||||
|
||||
Reference in New Issue
Block a user