@@ -62,19 +62,49 @@ 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+
6596/**
6697 * Gets a reference to `func`. `func` must be defined inside a class, and the reference
6798 * will be inside a different method of the same class.
6899 */
69100private DataFlow:: Node getSimpleMethodReferenceWithinClass ( Function func ) {
70101 // TODO: Should take MRO into account
71- exists ( Class cls , Function otherFunc , DataFlow :: Node selfRefOtherFunc |
102+ exists ( Class cls , Function otherFunc |
72103 cls .getAMethod ( ) = func and
73104 cls .getAMethod ( ) = otherFunc
74105 |
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 ) )
78108 )
79109}
80110
0 commit comments