mirror of
https://github.com/github/codeql.git
synced 2026-04-29 18:55:14 +02:00
C#: Dispatch library performance tweaks
- Restrict `OverridableCallable::getAnOverrider(ValueOrRefType t)` to types `t` that are sub types of the callable's declaring type. - Use explicit recursion in `OverridableCallable::getInherited()`.
This commit is contained in:
@@ -202,7 +202,7 @@ private module Internal {
|
||||
* Gets a non-exact (see `hasQualifierType()`) qualifier type of this call
|
||||
* that does not contain type parameters.
|
||||
*/
|
||||
TypeWithoutTypeParameters getANonExactQualifierTypeWithoutTypeParameters() {
|
||||
private TypeWithoutTypeParameters getANonExactQualifierTypeWithoutTypeParameters() {
|
||||
exists(Type qualifierType | hasQualifierType(qualifierType, false) |
|
||||
// Qualifier type contains no type parameters: use it
|
||||
result = qualifierType
|
||||
@@ -220,6 +220,20 @@ private module Internal {
|
||||
result = qualifierType.(QualifierTypeWithTypeParameters).getAPotentialInstance()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a non-exact (see `hasQualifierType()`) qualifier type of this call.
|
||||
*/
|
||||
ValueOrRefType getANonExactQualifierType() {
|
||||
exists(TypeWithoutTypeParameters t |
|
||||
t = this.getANonExactQualifierTypeWithoutTypeParameters()
|
||||
|
|
||||
result.(ConstructedType).getUnboundGeneric() = t
|
||||
or
|
||||
not t instanceof UnboundGenericType and
|
||||
result = t
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class DynamicFieldOrProperty extends Assignable {
|
||||
@@ -480,9 +494,9 @@ private module Internal {
|
||||
* qualifier types are `B.M` and `C.M`, `C.M`, and none, respectively.
|
||||
*/
|
||||
private RuntimeInstanceMethod getAViableOverrider() {
|
||||
exists(TypeWithoutTypeParameters t, NonConstructedOverridableMethod m |
|
||||
t = getANonExactQualifierTypeWithoutTypeParameters() and
|
||||
getAStaticTarget() = m.getAConstructingMethodOrSelf() and
|
||||
exists(ValueOrRefType t, NonConstructedOverridableMethod m |
|
||||
t = this.getANonExactQualifierType() and
|
||||
this.getAStaticTarget() = m.getAConstructingMethodOrSelf() and
|
||||
result = m.getAnOverrider(t)
|
||||
)
|
||||
}
|
||||
@@ -620,9 +634,9 @@ private module Internal {
|
||||
* respectively.
|
||||
*/
|
||||
private RuntimeAccessor getAViableOverrider() {
|
||||
exists(TypeWithoutTypeParameters t |
|
||||
t = getANonExactQualifierTypeWithoutTypeParameters() and
|
||||
result = getAStaticTarget().(OverridableAccessor).getAnOverrider(t)
|
||||
exists(ValueOrRefType t |
|
||||
t = this.getANonExactQualifierType() |
|
||||
result = this.getAStaticTarget().(OverridableAccessor).getAnOverrider(t)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,27 +135,33 @@ class OverridableCallable extends Callable {
|
||||
* - `C2.M = C2.M.getInherited(C3)`.
|
||||
*/
|
||||
Callable getInherited(SourceDeclarationType t) {
|
||||
exists(Callable sourceDecl | result = getInherited1(t, sourceDecl) |
|
||||
exists(Callable sourceDecl | result = this.getInherited2(t, sourceDecl) |
|
||||
hasSourceDeclarationCallable(t, sourceDecl)
|
||||
)
|
||||
}
|
||||
|
||||
private Callable getInherited0(SourceDeclarationType t) {
|
||||
private Callable getInherited0(ValueOrRefType t) {
|
||||
// A (transitive, reflexive) overrider
|
||||
t = this.hasOverrider(result).getASubType*().getSourceDeclaration()
|
||||
t = this.hasOverrider(result)
|
||||
or
|
||||
// A (transitive) overrider of an interface implementation
|
||||
t = this.hasOverridingImplementor(result)
|
||||
or
|
||||
exists(ValueOrRefType mid | result = this.getInherited0(mid) | t = mid.getASubType())
|
||||
}
|
||||
|
||||
private Callable getInherited1(SourceDeclarationType t) {
|
||||
exists(ValueOrRefType t0 | result = getInherited0(t0) | t = t0.getSourceDeclaration())
|
||||
or
|
||||
// An interface implementation
|
||||
exists(ValueOrRefType s |
|
||||
result = getAnImplementorSubType(s) and
|
||||
t = s.getSourceDeclaration()
|
||||
)
|
||||
or
|
||||
// A (transitive) overrider of an interface implementation
|
||||
t = this.hasOverridingImplementor(result).getASubType*().getSourceDeclaration()
|
||||
}
|
||||
|
||||
private Callable getInherited1(SourceDeclarationType t, Callable sourceDecl) {
|
||||
result = this.getInherited0(t) and
|
||||
private Callable getInherited2(SourceDeclarationType t, Callable sourceDecl) {
|
||||
result = this.getInherited1(t) and
|
||||
sourceDecl = result.getSourceDeclaration()
|
||||
}
|
||||
|
||||
@@ -171,9 +177,42 @@ class OverridableCallable extends Callable {
|
||||
result = c.getDeclaringType()
|
||||
}
|
||||
|
||||
private predicate isDeclaringSubType(ValueOrRefType t) {
|
||||
t = this.getDeclaringType()
|
||||
or
|
||||
exists(ValueOrRefType mid | isDeclaringSubType(mid) | t = mid.getASubType())
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private Callable getAnOverrider0(ValueOrRefType t) {
|
||||
not this.declaredInTypeWithTypeParameters() and
|
||||
(
|
||||
// A (transitive) overrider
|
||||
result = this.getAnOverrider+() and
|
||||
t = result.getDeclaringType()
|
||||
or
|
||||
// An interface implementation
|
||||
result = this.getAnImplementorSubType(t)
|
||||
or
|
||||
// A (transitive) overrider of an interface implementation
|
||||
result = this.getAnOverridingImplementor() and
|
||||
t = result.getDeclaringType()
|
||||
)
|
||||
}
|
||||
|
||||
private Callable getAnOverrider1(ValueOrRefType t) {
|
||||
result = this.getAnOverrider0(t)
|
||||
or
|
||||
exists(ValueOrRefType mid | result = this.getAnOverrider1(mid) |
|
||||
t = mid.getABaseType() and
|
||||
this.isDeclaringSubType(t)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a callable defined in a sub type of `t` that overrides/implements
|
||||
* this callable, if any.
|
||||
* Gets a callable defined in a sub type of `t` (which is itself a sub type
|
||||
* of this callable's declaring type) that overrides/implements this callable,
|
||||
* if any.
|
||||
*
|
||||
* The type `t` may be a constructed type: For example, if `t = C<int>`,
|
||||
* then only callables defined in sub types of `C<int>` (and e.g. not
|
||||
@@ -181,39 +220,7 @@ class OverridableCallable extends Callable {
|
||||
* contains a callable that overrides this callable, then only if `C2<int>`
|
||||
* is ever constructed will the callable in `C2` be considered valid.
|
||||
*/
|
||||
Callable getAnOverrider(TypeWithoutTypeParameters t) {
|
||||
exists(OverridableCallable oc, ValueOrRefType sub |
|
||||
result = oc.getAnOverriderAux(sub) and
|
||||
t = oc.getAnOverriderBaseType(sub) and
|
||||
oc = getABoundInstance()
|
||||
)
|
||||
}
|
||||
|
||||
// predicate folding to get proper join order
|
||||
private Callable getAnOverriderAux(ValueOrRefType t) {
|
||||
not declaredInTypeWithTypeParameters() and
|
||||
(
|
||||
// A (transitive) overrider
|
||||
result = getAnOverrider+() and
|
||||
t = result.getDeclaringType()
|
||||
or
|
||||
// An interface implementation
|
||||
result = getAnImplementorSubType(t)
|
||||
or
|
||||
// A (transitive) overrider of an interface implementation
|
||||
result = getAnOverridingImplementor() and
|
||||
t = result.getDeclaringType()
|
||||
)
|
||||
}
|
||||
|
||||
private TypeWithoutTypeParameters getAnOverriderBaseType(ValueOrRefType t) {
|
||||
exists(getAnOverriderAux(t)) and
|
||||
exists(Type t0 | t0 = t.getABaseType*() |
|
||||
result = t0
|
||||
or
|
||||
result = t0.(ConstructedType).getUnboundGeneric()
|
||||
)
|
||||
}
|
||||
Callable getAnOverrider(ValueOrRefType t) { result = this.getABoundInstance().getAnOverrider1(t) }
|
||||
|
||||
/**
|
||||
* Gets a bound instance of this callable.
|
||||
@@ -264,7 +271,7 @@ class OverridableMethod extends Method, OverridableCallable {
|
||||
result = OverridableCallable.super.getInherited(t)
|
||||
}
|
||||
|
||||
override Method getAnOverrider(TypeWithoutTypeParameters t) {
|
||||
override Method getAnOverrider(ValueOrRefType t) {
|
||||
result = OverridableCallable.super.getAnOverrider(t)
|
||||
}
|
||||
}
|
||||
@@ -311,7 +318,7 @@ class OverridableAccessor extends Accessor, OverridableCallable {
|
||||
result = OverridableCallable.super.getInherited(t)
|
||||
}
|
||||
|
||||
override Accessor getAnOverrider(TypeWithoutTypeParameters t) {
|
||||
override Accessor getAnOverrider(ValueOrRefType t) {
|
||||
result = OverridableCallable.super.getAnOverrider(t)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user