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

Skip to content

Commit 7825642

Browse files
committed
C#: Dispatch.qll performance tweaks
1 parent d0c442a commit 7825642

1 file changed

Lines changed: 52 additions & 42 deletions

File tree

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

Lines changed: 52 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -222,27 +222,55 @@ private module Internal {
222222
}
223223
}
224224

225-
private class FieldOrProperty extends Assignable {
226-
FieldOrProperty() {
227-
this instanceof Field or
228-
this instanceof Property
225+
private class DynamicFieldOrProperty extends Assignable {
226+
DynamicFieldOrProperty() {
227+
(
228+
this instanceof Field or
229+
this instanceof Property
230+
) and
231+
this.getName() = any(DynamicMemberAccess dma).getLateBoundTargetName()
232+
}
233+
234+
predicate isMemberOf(string name, ValueOrRefType t) {
235+
name = this.getName() and t.hasMember(this)
236+
}
237+
}
238+
239+
private class TypeWithDynamicFieldOrProperty extends ValueOrRefType {
240+
DynamicFieldOrProperty fp;
241+
242+
TypeWithDynamicFieldOrProperty() { fp.isMemberOf(_, this) }
243+
244+
predicate isImplicitlyConvertibleTo(string name, Type t) {
245+
name = fp.getName() and
246+
this.isImplicitlyConvertibleTo(t)
229247
}
230248
}
231249

250+
pragma[noinline]
251+
private predicate isPossibleDynamicMemberAccessQualifierType(
252+
DynamicMemberAccess dma, string name, TypeWithDynamicFieldOrProperty t
253+
) {
254+
exists(Type qt, boolean isExact |
255+
qt = getAPossibleType(dma.getQualifier(), isExact) and
256+
name = dma.getLateBoundTargetName()
257+
|
258+
isExact = true and t = qt
259+
or
260+
isExact = false and t.isImplicitlyConvertibleTo(name, qt)
261+
)
262+
}
263+
232264
/**
233265
* Gets a possible type for expression `e`. Simple flow is used to track the
234266
* origin of `e`, and in case `e` is a dynamic member access, only types
235267
* corresponding to the type of a relevant field or property are included.
236268
*/
237269
private Type getAPossibleType(Expr e, boolean isExact) {
238-
exists(ValueOrRefType qualifierType, FieldOrProperty fp, boolean qualifierTypeIsExact |
239-
qualifierType = getAPossibleTypeDynamicMemberAccessQualifier(e, qualifierTypeIsExact, fp)
270+
exists(DynamicFieldOrProperty fp, string name, TypeWithDynamicFieldOrProperty t |
271+
isPossibleDynamicMemberAccessQualifierType(e, name, t) and
272+
fp.isMemberOf(name, t)
240273
|
241-
(
242-
if qualifierTypeIsExact = true
243-
then qualifierType.hasMember(fp)
244-
else fp.getDeclaringType().isImplicitlyConvertibleTo(qualifierType)
245-
) and
246274
result = fp.getType() and
247275
isExact = false
248276
)
@@ -251,13 +279,6 @@ private module Internal {
251279
result = getASourceType(e, isExact)
252280
}
253281

254-
private Type getAPossibleTypeDynamicMemberAccessQualifier(
255-
DynamicMemberAccess dma, boolean isExact, FieldOrProperty fp
256-
) {
257-
result = getAPossibleType(dma.getQualifier(), isExact) and
258-
fp.getName() = dma.getLateBoundTargetName()
259-
}
260-
261282
/**
262283
* Provides the predicate `getASourceType()` for finding all relevant source
263284
* types for a given expression.
@@ -799,22 +820,14 @@ private module Internal {
799820
// conflicting types (for example, `Tuple<int, string>` is considered
800821
// compatible with `Tuple<T, T>`).
801822
override RuntimeCallable getADynamicTarget() {
802-
// Condition 1
803-
result = getADynamicTargetCandidate() and
804-
// Condition 2
805-
forall(int i | i in [0 .. getNumberOfArguments() - 1] |
806-
result = getADynamicTargetCandidateWithCompatibleArg(i)
807-
)
808-
}
809-
810-
private RuntimeCallable getADynamicTargetCandidateWithCompatibleArg(int i) {
811-
result = getADynamicTargetCandidateWithCompatibleArg1(i) or
812-
result = getADynamicTargetCandidateWithCompatibleArg2(i)
823+
result = this.getADynamicTarget(this.getNumberOfArguments() - 1)
813824
}
814825

815-
pragma[noinline]
816-
private RuntimeCallable getADynamicTargetCandidateWithCompatibleArg1(int i) {
817-
result = this.getADynamicTargetCandidate() and
826+
private RuntimeCallable getADynamicTarget(int i) {
827+
i = -1 and
828+
result = this.getADynamicTargetCandidate()
829+
or
830+
result = this.getADynamicTarget(i - 1) and
818831
exists(Type parameterType, Type argumentType |
819832
parameterType = this.getAParameterType(result, i) and
820833
argumentType = getAPossibleType(this.getArgument(i), _)
@@ -827,6 +840,12 @@ private module Internal {
827840
or
828841
reflectionOrDynamicArgEqualsParamModuloTypeParameters(argumentType, parameterType)
829842
)
843+
or
844+
result = this.getADynamicTarget(i - 1) and
845+
exists(Type parameterType, Type t | parameterType = this.getAParameterType(result, i) |
846+
this.argumentConvConstExpr(i, t) and
847+
t.isImplicitlyConvertibleTo(parameterType)
848+
)
830849
}
831850

832851
private Type getAParameterType(RuntimeCallable c, int i) {
@@ -840,15 +859,6 @@ private module Internal {
840859
)
841860
}
842861

843-
pragma[noinline]
844-
private RuntimeCallable getADynamicTargetCandidateWithCompatibleArg2(int i) {
845-
result = this.getADynamicTargetCandidate() and
846-
exists(Type parameterType, Type t | parameterType = this.getAParameterType(result, i) |
847-
this.argumentConvConstExpr(i, t) and
848-
t.isImplicitlyConvertibleTo(parameterType)
849-
)
850-
}
851-
852862
pragma[noinline]
853863
private predicate argumentConvConstExpr(int i, Type t) {
854864
convConstantExpr(this.getArgument(i), t)
@@ -954,7 +964,7 @@ private module Internal {
954964
*/
955965
private predicate isReflectionOrDynamicCallArgumentWithTypeParameters(Type argType, Type paramType) {
956966
exists(DispatchReflectionOrDynamicCall call, Parameter p, int i, int j |
957-
p = call.getAStaticTarget().getParameter(i) and
967+
p = call.getADynamicTargetCandidate().getParameter(i) and
958968
(
959969
if p.isParams()
960970
then (

0 commit comments

Comments
 (0)