Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d5cc42e

Browse files
committed
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.
1 parent 3049bf2 commit d5cc42e

1 file changed

Lines changed: 33 additions & 16 deletions

File tree

python/ql/src/Statements/StatementNoEffect.ql

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -49,28 +49,45 @@ predicate side_effecting_descriptor_type(ClassObject descriptor) {
4949
* side-effecting unless we know otherwise.
5050
*/
5151
predicate side_effecting_binary(Expr b) {
52-
exists(Expr sub, string method_name |
53-
sub = b.(BinaryExpr).getLeft() and
54-
method_name = b.(BinaryExpr).getOp().getSpecialMethodName()
52+
exists(Expr sub, ClassObject cls, string method_name |
53+
binary_operator_special_method(b, sub, cls, method_name)
5554
or
56-
exists(Cmpop op |
57-
b.(Compare).compares(sub, op, _) and
58-
method_name = op.getSpecialMethodName()
59-
)
55+
comparison_special_method(b, sub, cls, method_name)
6056
|
61-
exists(ClassObject cls |
62-
sub.refersTo(_, cls, _) and
63-
cls.hasAttribute(method_name)
64-
and
65-
not exists(ClassObject declaring |
66-
declaring.declaresAttribute(method_name)
67-
and declaring = cls.getAnImproperSuperType() and
68-
declaring.isBuiltin() and not declaring = theObjectType()
69-
)
57+
method_name = special_method() and
58+
cls.hasAttribute(method_name)
59+
and
60+
not exists(ClassObject declaring |
61+
declaring.declaresAttribute(method_name)
62+
and declaring = cls.getAnImproperSuperType() and
63+
declaring.isBuiltin() and not declaring = theObjectType()
7064
)
7165
)
7266
}
7367

68+
pragma[nomagic]
69+
private predicate binary_operator_special_method(BinaryExpr b, Expr sub, ClassObject cls, string method_name) {
70+
method_name = special_method() and
71+
sub = b.getLeft() and
72+
method_name = b.getOp().getSpecialMethodName() and
73+
sub.refersTo(_, cls, _)
74+
}
75+
76+
pragma[nomagic]
77+
private predicate comparison_special_method(Compare b, Expr sub, ClassObject cls, string method_name) {
78+
exists(Cmpop op |
79+
b.compares(sub, op, _) and
80+
method_name = op.getSpecialMethodName()
81+
) and
82+
sub.refersTo(_, cls, _)
83+
}
84+
85+
private string special_method() {
86+
result = any(Cmpop c).getSpecialMethodName()
87+
or
88+
result = any(BinaryExpr b).getOp().getSpecialMethodName()
89+
}
90+
7491
predicate is_notebook(File f) {
7592
exists(Comment c |
7693
c.getLocation().getFile() = f |

0 commit comments

Comments
 (0)