Skip to content

Commit f5471e3

Browse files
committed
C#: Fix bad join-order in dispatch library
Before ``` [2021-12-22 09:46:31] (395s) Tuple counts for Dispatch::Internal::hasCallable#fff/3@258418l2 after 5m27s: 49000 ~0% {2} r1 = JOIN Declaration::Declaration::getUnboundDeclaration_dispred#ff_10#join_rhs WITH project#Dispatch::Internal::DispatchMethodOrAccessorCall::getAStaticTargetExt#ff ON FIRST 1 OUTPUT Lhs.1 'c', Rhs.0 31302 ~3% {3} r2 = JOIN r1 WITH Type::ValueOrRefType::getAMember_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.0 'c', Lhs.1 'source', Rhs.1 299700 ~0% {3} r3 = JOIN r1 WITH Type::ValueOrRefType::hasOverriddenMember_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.0 'c', Lhs.1 'source', Rhs.1 16650 ~1% {3} r4 = JOIN r1 WITH Property::Accessor::getDeclaration_dispred#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'source', Lhs.0 'c' 15984 ~0% {3} r5 = JOIN r4 WITH Type::ValueOrRefType::getAMember_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.2 'c', Lhs.1 'source', Rhs.1 315684 ~1% {3} r6 = r3 UNION r5 346986 ~1% {3} r7 = r2 UNION r6 0 ~0% {3} r8 = JOIN r4 WITH Type::ValueOrRefType::hasOverriddenMember_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.2 'c', Lhs.1 'source', Rhs.1 666 ~0% {3} r9 = JOIN r1 WITH Type::hasNonOverriddenMember#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'source', Lhs.0 'c' 0 ~0% {3} r10 = JOIN r9 WITH boundedFastTC(Type::ValueOrRefType::getBaseClass_dispred#ff_10#join_rhs,Dispatch::Internal::hasCallable#fff#higher_order_body) ON FIRST 1 OUTPUT Lhs.2 'c', Lhs.1 'source', Rhs.1 0 ~0% {3} r11 = JOIN r4 WITH Type::hasNonOverriddenMember#ff_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'source', Lhs.2 'c' 0 ~0% {3} r12 = JOIN r11 WITH boundedFastTC(Type::ValueOrRefType::getBaseClass_dispred#ff_10#join_rhs,Dispatch::Internal::hasCallable#fff#higher_order_body#1) ON FIRST 1 OUTPUT Lhs.2 'c', Lhs.1 'source', Rhs.1 0 ~0% {3} r13 = r10 UNION r12 0 ~0% {3} r14 = r8 UNION r13 346986 ~1% {3} r15 = r7 UNION r14 11963234000 ~2% {4} r16 = JOIN r15 WITH Dispatch::Internal::hasOverrider#ff ON FIRST 1 OUTPUT Lhs.2, Rhs.1 't', Lhs.1 'source', Lhs.0 'c' 207126 ~27% {3} r17 = JOIN r16 WITH Unification::Gvn::Cached::getGlobalValueNumber#ff ON FIRST 2 OUTPUT Lhs.2 'source', Lhs.1 't', Lhs.3 'c' return r17 ``` After ``` [2021-12-22 10:39:41] (0s) Tuple counts for Dispatch::Internal::hasCallable0#fff/3@82341e2h after 331ms: 93569 ~0% {2} r1 = JOIN Type::ValueOrRefType::getAMember_dispred#fb_10#join_rhs WITH OverridableCallable::OverridableCallable#f ON FIRST 1 OUTPUT Rhs.0 'c', Lhs.1 511767 ~0% {2} r2 = JOIN Type::ValueOrRefType::hasOverriddenMember_dispred#ff_10#join_rhs WITH OverridableCallable::OverridableCallable#f ON FIRST 1 OUTPUT Rhs.0 'c', Lhs.1 35659 ~0% {2} r3 = JOIN OverridableCallable::OverridableCallable#f WITH Property::Accessor::getDeclaration_dispred#ff ON FIRST 1 OUTPUT Rhs.1, Lhs.0 'c' 35659 ~4% {2} r4 = JOIN r3 WITH Type::ValueOrRefType::getAMember_dispred#fb_10#join_rhs ON FIRST 1 OUTPUT Lhs.1 'c', Rhs.1 547426 ~0% {2} r5 = r2 UNION r4 640995 ~4% {2} r6 = r1 UNION r5 74835 ~4% {2} r7 = JOIN r3 WITH Type::ValueOrRefType::hasOverriddenMember_dispred#ff_10#join_rhs ON FIRST 1 OUTPUT Lhs.1 'c', Rhs.1 32748 ~0% {2} r8 = JOIN Type::hasNonOverriddenMember#fb_10#join_rhs WITH OverridableCallable::OverridableCallable#f ON FIRST 1 OUTPUT Lhs.1, Rhs.0 'c' 171228 ~0% {2} r9 = JOIN r8 WITH boundedFastTC(Type::ValueOrRefType::getBaseClass_dispred#ff_10#join_rhs,Dispatch::Internal::hasCallable0#fff#higher_order_body) ON FIRST 1 OUTPUT Lhs.1 'c', Rhs.1 9056 ~0% {2} r10 = JOIN r3 WITH Type::hasNonOverriddenMember#fb_10#join_rhs ON FIRST 1 OUTPUT Rhs.1, Lhs.1 'c' 23633 ~1% {2} r11 = JOIN r10 WITH boundedFastTC(Type::ValueOrRefType::getBaseClass_dispred#ff_10#join_rhs,Dispatch::Internal::hasCallable0#fff#higher_order_body#1) ON FIRST 1 OUTPUT Lhs.1 'c', Rhs.1 194861 ~0% {2} r12 = r9 UNION r11 269696 ~0% {2} r13 = r7 UNION r12 910691 ~4% {2} r14 = r6 UNION r13 910691 ~2% {3} r15 = JOIN r14 WITH Declaration::Declaration::getUnboundDeclaration_dispred#ff ON FIRST 1 OUTPUT Rhs.1 'source', Lhs.0 'c', Lhs.1 579872 ~2% {3} r16 = JOIN r15 WITH project#Dispatch::Internal::DispatchMethodOrAccessorCall::getAStaticTargetExt#ff ON FIRST 1 OUTPUT Lhs.2, Lhs.1 'c', Lhs.0 'source' 753465 ~41% {3} r17 = JOIN r16 WITH Unification::Gvn::Cached::getGlobalValueNumber#ff ON FIRST 1 OUTPUT Rhs.1 't', Lhs.1 'c', Lhs.2 'source' return r17 [2021-12-22 10:39:41] (0s) Tuple counts for Dispatch::Internal::hasCallable#fff/3@e44e67tv after 24ms: 201843 ~0% {3} r1 = JOIN Dispatch::Internal::hasOverrider#ff WITH Dispatch::Internal::hasCallable0#fff ON FIRST 2 OUTPUT Lhs.0 't', Lhs.1 'c', Rhs.2 'source' return r1 ```
1 parent dae5af6 commit f5471e3

File tree

1 file changed

+11
-6
lines changed

1 file changed

+11
-6
lines changed

csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -233,18 +233,23 @@ private module Internal {
233233
}
234234

235235
pragma[noinline]
236-
private predicate hasOverrider(OverridableCallable oc, Gvn::GvnType t) {
236+
private predicate hasOverrider(Gvn::GvnType t, OverridableCallable oc) {
237237
exists(oc.getAnOverrider(any(ValueOrRefType t0 | Gvn::getGlobalValueNumber(t0) = t)))
238238
}
239239

240240
pragma[noinline]
241-
private predicate hasCallable(OverridableCallable source, Gvn::GvnType t, OverridableCallable c) {
241+
private predicate hasCallable0(Gvn::GvnType t, OverridableCallable c, OverridableCallable source) {
242242
c.getUnboundDeclaration() = source and
243243
any(ValueOrRefType t0 | Gvn::getGlobalValueNumber(t0) = t).hasCallable(c) and
244-
hasOverrider(c, t) and
245244
source = any(DispatchMethodOrAccessorCall call).getAStaticTargetExt()
246245
}
247246

247+
pragma[noinline]
248+
private predicate hasCallable(Gvn::GvnType t, OverridableCallable c, OverridableCallable source) {
249+
hasCallable0(t, c, source) and
250+
hasOverrider(t, c)
251+
}
252+
248253
abstract private class DispatchMethodOrAccessorCall extends DispatchCallImpl {
249254
pragma[noinline]
250255
OverridableCallable getAStaticTargetExt() {
@@ -260,7 +265,7 @@ private module Internal {
260265

261266
pragma[noinline]
262267
private predicate hasSubsumedQualifierType(Gvn::GvnType t) {
263-
hasOverrider(_, t) and
268+
hasOverrider(t, _) and
264269
exists(Type t0 |
265270
t0 = getAPossibleType(this.getQualifier(), false) and
266271
not t0 instanceof TypeParameter
@@ -287,7 +292,7 @@ private module Internal {
287292
pragma[nomagic]
288293
predicate hasSubsumedQualifierTypeOverridden(Gvn::GvnType t, OverridableCallable c) {
289294
this.hasSubsumedQualifierType(t) and
290-
hasCallable(any(OverridableCallable oc | oc = this.getAStaticTargetExt()), t, c)
295+
hasCallable(t, c, any(OverridableCallable oc | oc = this.getAStaticTargetExt()))
291296
}
292297

293298
/**
@@ -553,7 +558,7 @@ private module Internal {
553558

554559
pragma[nomagic]
555560
private predicate contextArgHasSubsumedType(DispatchCall ctx, Gvn::GvnType t) {
556-
hasOverrider(_, t) and
561+
hasOverrider(t, _) and
557562
exists(Gvn::GvnType t0 | this.contextArgHasNonTypeParameterType(ctx, t0) |
558563
t = t0
559564
or

0 commit comments

Comments
 (0)