@@ -62,19 +62,49 @@ private DataFlow::TypeTrackingNode poorMansFunctionTracker(DataFlow::TypeTracker
62
62
exists ( DataFlow:: TypeTracker t2 | result = poorMansFunctionTracker ( t2 , func ) .track ( t2 , t ) )
63
63
}
64
64
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
+
65
96
/**
66
97
* Gets a reference to `func`. `func` must be defined inside a class, and the reference
67
98
* will be inside a different method of the same class.
68
99
*/
69
100
private DataFlow:: Node getSimpleMethodReferenceWithinClass ( Function func ) {
70
101
// TODO: Should take MRO into account
71
- exists ( Class cls , Function otherFunc , DataFlow :: Node selfRefOtherFunc |
102
+ exists ( Class cls , Function otherFunc |
72
103
cls .getAMethod ( ) = func and
73
104
cls .getAMethod ( ) = otherFunc
74
105
|
75
- selfRefOtherFunc .getALocalSource ( ) .( DataFlow:: ParameterNode ) .getParameter ( ) =
76
- otherFunc .getArg ( 0 ) and
77
- result .( DataFlow:: AttrRead ) .accesses ( selfRefOtherFunc , func .getName ( ) )
106
+ getSimpleMethodReferenceWithinClass_helper2 ( pragma [ only_bind_into ] ( otherFunc ) ,
107
+ pragma [ only_bind_into ] ( cls ) , pragma [ only_bind_into ] ( result ) , pragma [ only_bind_into ] ( func ) )
78
108
)
79
109
}
80
110
0 commit comments