Skip to content

Commit b65da76

Browse files
author
maximv
committed
optimize EmitMethodCall to call the ILGenerator.EmitCall where available
1 parent 586af7a commit b65da76

File tree

3 files changed

+38
-34
lines changed

3 files changed

+38
-34
lines changed

src/FastExpressionCompiler/FastExpressionCompiler.cs

Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ THE SOFTWARE.
3737
#if LIGHT_EXPRESSION || !NET45
3838
#define SUPPORTS_ARGUMENT_PROVIDER
3939
#endif
40+
#if !NETSTANDARD2_0
41+
#define SUPPORTS_EMITCALL
42+
#endif
4043
#if LIGHT_EXPRESSION
4144
using static FastExpressionCompiler.LightExpression.Expression;
4245
using PE = FastExpressionCompiler.LightExpression.ParameterExpression;
@@ -2077,11 +2080,11 @@ private static bool TryEmitIndex(IndexExpression indexExpr, IReadOnlyList<PE> p
20772080
if (indexerPropGetter != null)
20782081
return EmitMethodCall(il, indexerPropGetter);
20792082

2080-
if (indexArgCount == 1) // one dimensional array
2083+
if (indexArgCount == 1) // one-dimensional array
20812084
return TryEmitArrayIndex(indexExpr.Type, il, parent, ref closure);
20822085

2083-
// multi dimensional array
2084-
return EmitMethodCall(il, indexExpr.Object?.Type.FindMethod("Get"));
2086+
indexerPropGetter = indexExpr.Object?.Type.FindMethod("Get"); // multi-dimensional array
2087+
return indexerPropGetter != null && EmitMethodCall(il, indexerPropGetter);
20852088
}
20862089

20872090
#if LIGHT_EXPRESSION
@@ -3313,11 +3316,7 @@ private static bool EmitMemberAssign(ILGenerator il, MemberInfo member)
33133316
if (member is PropertyInfo prop)
33143317
{
33153318
var method = prop.DeclaringType.FindPropertySetMethod(prop.Name);
3316-
if (method == null)
3317-
return false;
3318-
3319-
il.Emit(method.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, method);
3320-
return true;
3319+
return method != null && EmitMethodCall(il, method);
33213320
}
33223321
if (member is FieldInfo field)
33233322
{
@@ -3400,7 +3399,7 @@ private static bool TryEmitListInit(ListInitExpression expr, IReadOnlyList<PE> p
34003399
return false;
34013400

34023401
if (!exprType.IsValueType)
3403-
il.Emit(method.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, method);
3402+
EmitMethodCall(il, method);
34043403
else if (!method.IsVirtual) // #251 - no need for constrain or virtual call because it is already by-ref
34053404
il.Emit(OpCodes.Call, method);
34063405
else if (method.DeclaringType == exprType)
@@ -3837,8 +3836,8 @@ private static bool TryEmitIndexAssign(IndexExpression indexExpr, Type instType,
38373836
return true;
38383837
}
38393838

3840-
// multi dimensional array
3841-
return EmitMethodCall(il, instType?.FindMethod("Set"));
3839+
var setter = instType?.FindMethod("Set");
3840+
return setter != null && EmitMethodCall(il, setter); // multi dimensional array
38423841
}
38433842

38443843
#if LIGHT_EXPRESSION
@@ -3883,7 +3882,7 @@ private static bool TryEmitMethodCall(Expression expr, IReadOnlyList<PE> paramE
38833882
}
38843883

38853884
if (!objIsValueType)
3886-
il.Emit(method.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, method);
3885+
EmitMethodCall(il, method);
38873886
else if (!method.IsVirtual || objExpr is ParameterExpression p && p.IsByRef)
38883887
il.Emit(OpCodes.Call, method);
38893888
else if (method.DeclaringType == objExpr.Type)
@@ -4496,7 +4495,7 @@ private static bool TryEmitArithmetic(BinaryExpression expr, ExpressionType expr
44964495
if (!TryEmitArithmeticOperation(expr, exprNodeType, exprType, il))
44974496
return false;
44984497

4499-
if (leftIsNullable || rightIsNullable)
4498+
if (leftIsNullable || rightIsNullable) // todo: @clarify that the code emitted is correct
45004499
{
45014500
var valueLabel = il.DefineLabel();
45024501
il.Emit(OpCodes.Br, valueLabel);
@@ -4581,10 +4580,7 @@ var methodName
45814580
}
45824581
}
45834582

4584-
if (method == null)
4585-
return false;
4586-
il.Emit(method.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, method);
4587-
return true;
4583+
return method != null && EmitMethodCall(il, method);
45884584
}
45894585
}
45904586

@@ -4855,15 +4851,14 @@ private static Expression TryReduceCondition(Expression testExpr)
48554851
return testExpr;
48564852
}
48574853

4858-
private static bool EmitMethodCall(ILGenerator il, MethodInfo method, ParentFlags parent = ParentFlags.Empty)
4854+
[MethodImpl((MethodImplOptions)256)]
4855+
private static bool EmitMethodCall(ILGenerator il, MethodInfo method)
48594856
{
4860-
if (method == null)
4861-
return false;
4862-
4857+
#if SUPPORTS_EMITCALL
4858+
il.EmitCall(method.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, method, null);
4859+
#else
48634860
il.Emit(method.IsVirtual ? OpCodes.Callvirt : OpCodes.Call, method);
4864-
4865-
if ((parent & ParentFlags.IgnoreResult) != 0 && method.ReturnType != typeof(void))
4866-
il.Emit(OpCodes.Pop);
4861+
#endif
48674862
return true;
48684863
}
48694864

test/FastExpressionCompiler.IssueTests/Issue274_Failing_Expressions_in_Linq2DB.cs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ public class Issue274_Failing_Expressions_in_Linq2DB : ITest
2121
{
2222
public int Run()
2323
{
24+
Test_287_Case2_SimpleDelegate_as_nested_lambda_in_TesCollection_test();
25+
2426
Test_287_Case1_ConvertTests_NullableParameterInOperatorConvert_VerificationException();
2527

2628
Test_283_Case6_MappingSchemaTests_CultureInfo_VerificationException();
@@ -41,7 +43,7 @@ public int Run()
4143
Test_case_1_Full_AccessViolationException();
4244
The_expression_with_anonymous_class_should_output_without_special_symbols();
4345

44-
return 16;
46+
return 17;
4547
}
4648

4749
[Test]
@@ -545,8 +547,7 @@ public void Test_287_Case2_SimpleDelegate_as_nested_lambda_in_TesCollection_test
545547
var p = new ParameterExpression[3]; // the parameter expressions
546548
var e = new Expression[8]; // the unique expressions
547549
var l = new LabelTarget[0]; // the labels
548-
var expr = Lambda( // $
549-
typeof(Dynamic.SimpleDelegate),
550+
var expr = Lambda<Action<SampleClass, string>>( // $
550551
e[0] = Block(
551552
typeof(void),
552553
new[] {
@@ -569,18 +570,20 @@ public void Test_287_Case2_SimpleDelegate_as_nested_lambda_in_TesCollection_test
569570
p[2] = Parameter(typeof(string))),
570571
e[7] = Empty(),
571572
typeof(void))),
572-
p[2 // (string string__41619574)
573-
]);
573+
p[1 // (SampleClass)
574+
],
575+
p[2 // (string string__41619574)
576+
]);
574577

575578
expr.PrintCSharp();
576579

577580
var fs = expr.CompileSys();
578581
fs.PrintIL();
579-
// Assert.AreEqual(new CustomMoneyType { Amount = 1.11m }, fs(1.11m));
582+
fs(new SampleClass(), "43");
580583

581584
var fx = expr.CompileFast(true);
582585
fx.PrintIL();
583-
// Assert.AreEqual(new CustomMoneyType { Amount = 1.11m }, fx(1.11m));
586+
fx(new SampleClass(), "43");
584587
}
585588

586589
[Test]

test/FastExpressionCompiler.IssueTests/Issue83_linq2db.cs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,9 +1235,15 @@ public void AddNullTest()
12351235
var p = Parameter(typeof(int?));
12361236
var body = Add(Constant(4, typeof(int?)), p);
12371237
var expr = Lambda<Func<int?, int?>>(body, p);
1238-
var compiled = expr.CompileFast(true);
1239-
Assert.AreEqual(9, compiled(5));
1240-
Assert.AreEqual(null, compiled(null));
1238+
1239+
var fs = expr.CompileSys();
1240+
fs.PrintIL();
1241+
1242+
var fx = expr.CompileFast(true);
1243+
fx.PrintIL();
1244+
1245+
Assert.AreEqual(9, fx(5));
1246+
Assert.AreEqual(null, fx(null));
12411247
}
12421248

12431249
[Test]

0 commit comments

Comments
 (0)