Speed up expression delegates when widening types is not needed

This commit is contained in:
Alexey Skalozub
2016-09-11 03:35:36 +03:00
parent deefe2e006
commit 7b0331725c
@@ -105,18 +105,7 @@ namespace Newtonsoft.Json.Utilities
Expression paramAccessorExpression = Expression.ArrayIndex(argsParameterExpression, indexExpression);
Expression argExpression;
if (parameterType.IsValueType())
{
BinaryExpression ensureValueTypeNotNull = Expression.Coalesce(paramAccessorExpression, Expression.New(parameterType));
argExpression = EnsureCastExpression(ensureValueTypeNotNull, parameterType);
}
else
{
argExpression = EnsureCastExpression(paramAccessorExpression, parameterType);
}
Expression argExpression = EnsureCastExpression(paramAccessorExpression, parameterType, !isByRef);
if (isByRef)
{
@@ -349,26 +338,39 @@ namespace Newtonsoft.Json.Utilities
Action<T, object> compiled = (Action<T, object>)lambdaExpression.Compile();
return compiled;
}
private Expression EnsureCastExpression(Expression expression, Type targetType)
private Expression EnsureCastExpression(Expression expression, Type targetType, bool allowWidening = false)
{
Type expressionType = expression.Type;
// check if a cast or conversion is required
if (expressionType == targetType || (!expressionType.IsValueType() && targetType.IsAssignableFrom(expressionType)))
{
return expression;
}
if (targetType.IsPrimitive())
if (targetType.IsValueType())
{
MethodInfo toTargetTypeMethod = typeof(Convert)
.GetMethod("To" + targetType.Name, new[] { typeof(object) });
Expression convert = Expression.Unbox(expression, targetType);
if (toTargetTypeMethod != null)
if (allowWidening && targetType.IsPrimitive())
{
expression = Expression.Call(toTargetTypeMethod, expression);
MethodInfo toTargetTypeMethod = typeof(Convert)
.GetMethod("To" + targetType.Name, new[] { typeof(object) });
if (toTargetTypeMethod != null)
{
convert = Expression.Condition(
Expression.TypeIs(expression, targetType),
convert,
Expression.Call(toTargetTypeMethod, expression));
}
}
return Expression.Condition(
Expression.Equal(expression, Expression.Constant(null, typeof(object))),
Expression.Default(targetType),
convert);
}
return Expression.Convert(expression, targetType);