Skip to content

Commit

Permalink
Introduce liftable constants to shaper to prepare for precompilation
Browse files Browse the repository at this point in the history
Part of #25009
  • Loading branch information
roji authored and maumar committed Mar 24, 2024
1 parent b299018 commit 3a7faf7
Show file tree
Hide file tree
Showing 165 changed files with 4,224 additions and 1,363 deletions.
1 change: 1 addition & 0 deletions EFCore.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ The .NET Foundation licenses this file to you under the MIT license.
<s:Boolean x:Key="/Default/UserDictionary/Words/=Includable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=initializers/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=keyless/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=liftable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Lite_0027s/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=materializer/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=materializers/@EntryIndexedValue">True</s:Boolean>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,10 @@ static bool IsTypeConstant(Expression expression, out Type? type)
}
}

private static readonly MethodInfo PropertyGetValueConverterMethod
= typeof(IReadOnlyProperty).GetMethod(nameof(IReadOnlyProperty.GetValueComparer))!;
//= typeof(IProperty).GetMethod(nameof(IProperty.GetValueComparer))!;

private static bool TryUseComparer(
Expression? newLeft,
Expression? newRight,
Expand Down Expand Up @@ -425,12 +429,20 @@ private static bool TryUseComparer(
updatedExpression =
exactMatch != null
? Expression.Call(
Expression.Constant(comparer, comparer.GetType()),
Expression.Convert(
Expression.Call(
Expression.Constant(property),
PropertyGetValueConverterMethod),
comparer.GetType()),
exactMatch,
newLeft,
newRight)
: Expression.Call(
Expression.Constant(comparer, comparer.GetType()),
Expression.Convert(
Expression.Call(
Expression.Constant(property),
PropertyGetValueConverterMethod),
comparer.GetType()),
objectEquals!,
Expression.Convert(newLeft, typeof(object)),
Expression.Convert(newRight, typeof(object)));
Expand Down
25 changes: 19 additions & 6 deletions src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.EntityFrameworkCore.InMemory.Internal;
using Microsoft.EntityFrameworkCore.Internal;
using ExpressionExtensions = Microsoft.EntityFrameworkCore.Infrastructure.ExpressionExtensions;

namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal;
Expand Down Expand Up @@ -896,6 +895,9 @@ private static Expression GetGroupingKey(Expression key, List<Expression> groupi
}
}

private static readonly MethodInfo PropertyGetValueConverterMethod
= typeof(IReadOnlyProperty).GetMethod(nameof(IReadOnlyProperty.GetValueComparer))!;

private Expression AddJoin(
InMemoryQueryExpression innerQueryExpression,
LambdaExpression? outerKeySelector,
Expand Down Expand Up @@ -1054,9 +1056,8 @@ private Expression AddJoin(
if (outerKeySelector != null
&& innerKeySelector != null)
{
var comparer = ((InferPropertyFromInner(outerKeySelector.Body)
?? InferPropertyFromInner(outerKeySelector.Body))
as IProperty)?.GetValueComparer();
var property = (InferPropertyFromInner(outerKeySelector.Body) ?? InferPropertyFromInner(outerKeySelector.Body)) as IProperty;
var comparer = property?.GetValueComparer();

if (comparer?.Type != outerKeySelector.ReturnType)
{
Expand All @@ -1074,7 +1075,13 @@ private Expression AddJoin(
innerKeySelector,
resultSelector,
Constant(new ValueBuffer(Enumerable.Repeat((object?)null, resultSelectorExpressions.Count - outerIndex).ToArray())),
Constant(comparer, typeof(IEqualityComparer<>).MakeGenericType(outerKeySelector.ReturnType)));
comparer != null
? Convert(
Call(
Constant(property),
PropertyGetValueConverterMethod),
typeof(IEqualityComparer<>).MakeGenericType(outerKeySelector.ReturnType))
: Constant(comparer, typeof(IEqualityComparer<>).MakeGenericType(outerKeySelector.ReturnType)));
}
else
{
Expand All @@ -1095,7 +1102,13 @@ private Expression AddJoin(
outerKeySelector,
innerKeySelector,
resultSelector,
Constant(comparer, typeof(IEqualityComparer<>).MakeGenericType(outerKeySelector.ReturnType)));
comparer != null
? Convert(
Call(
Constant(property),
PropertyGetValueConverterMethod),
typeof(IEqualityComparer<>).MakeGenericType(outerKeySelector.ReturnType))
: Constant(comparer, typeof(IEqualityComparer<>).MakeGenericType(outerKeySelector.ReturnType)));
}
}
else
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using Microsoft.EntityFrameworkCore.Query.Internal;
using static System.Linq.Expressions.Expression;
using ExpressionExtensions = Microsoft.EntityFrameworkCore.Infrastructure.ExpressionExtensions;

Expand Down Expand Up @@ -132,14 +133,23 @@ protected override Expression VisitExtension(Expression extensionExpression)
IncludeCollectionMethodInfo.MakeGenericMethod(entityClrType, includingClrType, relatedEntityClrType),
QueryCompilationContext.QueryContextParameter,
Visit(collectionResultShaperExpression.Projection),
Constant(shaperLambda.Compile()),
shaperLambda,
entity,
Constant(includeExpression.Navigation),
Constant(inverseNavigation, typeof(INavigationBase)),
Constant(
GenerateFixup(
includingClrType, relatedEntityClrType, includeExpression.Navigation, inverseNavigation)
.Compile()),
_inMemoryShapedQueryCompilingExpressionVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant(
Constant(includeExpression.Navigation),
#pragma warning disable EF1001 // Internal EF Core API usage.
LiftableConstantExpressionHelpers.BuildNavigationAccessLambda(includeExpression.Navigation),
#pragma warning restore EF1001 // Internal EF Core API usage.
includeExpression.Navigation + "Navigation",
typeof(INavigationBase)),
_inMemoryShapedQueryCompilingExpressionVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant(
Constant(inverseNavigation, typeof(INavigationBase)),
#pragma warning disable EF1001 // Internal EF Core API usage.
LiftableConstantExpressionHelpers.BuildNavigationAccessLambda(includeExpression.Navigation),
#pragma warning restore EF1001 // Internal EF Core API usage.
inverseNavigation + "InverseNavigation",
typeof(INavigationBase)),
GenerateFixup(includingClrType, relatedEntityClrType, includeExpression.Navigation, inverseNavigation),
Constant(_tracking),
#pragma warning disable EF1001 // Internal EF Core API usage.
Constant(includeExpression.SetLoaded)));
Expand All @@ -153,12 +163,21 @@ protected override Expression VisitExtension(Expression extensionExpression)
QueryCompilationContext.QueryContextParameter,
entity,
Visit(includeExpression.NavigationExpression),
Constant(includeExpression.Navigation),
Constant(inverseNavigation, typeof(INavigationBase)),
Constant(
GenerateFixup(
includingClrType, relatedEntityClrType, includeExpression.Navigation, inverseNavigation)
.Compile()),
_inMemoryShapedQueryCompilingExpressionVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant(
Constant(includeExpression.Navigation),
#pragma warning disable EF1001 // Internal EF Core API usage.
LiftableConstantExpressionHelpers.BuildNavigationAccessLambda(includeExpression.Navigation),
#pragma warning restore EF1001 // Internal EF Core API usage.
includeExpression.Navigation + "Navigation",
typeof(INavigationBase)),
_inMemoryShapedQueryCompilingExpressionVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant(
Constant(inverseNavigation, typeof(INavigationBase)),
#pragma warning disable EF1001 // Internal EF Core API usage.
LiftableConstantExpressionHelpers.BuildNavigationAccessLambda(includeExpression.Navigation),
#pragma warning restore EF1001 // Internal EF Core API usage.
inverseNavigation + "InverseNavigation",
typeof(INavigationBase)),
GenerateFixup(includingClrType, relatedEntityClrType, includeExpression.Navigation, inverseNavigation),
Constant(_tracking)));
}

Expand All @@ -179,8 +198,16 @@ protected override Expression VisitExtension(Expression extensionExpression)
MaterializeCollectionMethodInfo.MakeGenericMethod(elementType, collectionType),
QueryCompilationContext.QueryContextParameter,
Visit(collectionResultShaperExpression.Projection),
Constant(shaperLambda.Compile()),
Constant(collectionAccessor, typeof(IClrCollectionAccessor)));
shaperLambda,
navigation != null
? _inMemoryShapedQueryCompilingExpressionVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant(
Constant(collectionAccessor, typeof(IClrCollectionAccessor)),
#pragma warning disable EF1001 // Internal EF Core API usage.
LiftableConstantExpressionHelpers.BuildClrCollectionAccessorLambda(navigation),
#pragma warning restore EF1001 // Internal EF Core API usage.
navigation.Name + "ClrCollectionAccessor",
typeof(IClrCollectionAccessor))
: Expression.Default(typeof(IClrCollectionAccessor)));
}

case SingleResultShaperExpression singleResultShaperExpression:
Expand All @@ -193,7 +220,7 @@ protected override Expression VisitExtension(Expression extensionExpression)
MaterializeSingleResultMethodInfo.MakeGenericMethod(singleResultShaperExpression.Type),
QueryCompilationContext.QueryContextParameter,
Visit(singleResultShaperExpression.Projection),
Constant(shaperLambda.Compile()));
shaperLambda);
}
}

Expand Down Expand Up @@ -361,7 +388,7 @@ private static TCollection MaterializeCollection<TElement, TCollection>(
? default
: innerShaper(queryContext, valueBuffer);

private static LambdaExpression GenerateFixup(
private LambdaExpression GenerateFixup(
Type entityType,
Type relatedEntityType,
INavigationBase navigation,
Expand Down Expand Up @@ -397,12 +424,18 @@ private static Expression AssignReferenceNavigation(
INavigationBase navigation)
=> entity.MakeMemberAccess(navigation.GetMemberInfo(forMaterialization: true, forSet: true)).Assign(relatedEntity);

private static Expression AddToCollectionNavigation(
private Expression AddToCollectionNavigation(
ParameterExpression entity,
ParameterExpression relatedEntity,
INavigationBase navigation)
=> Call(
Constant(navigation.GetCollectionAccessor()),
_inMemoryShapedQueryCompilingExpressionVisitor.Dependencies.LiftableConstantFactory.CreateLiftableConstant(
Constant(navigation.GetCollectionAccessor()),
#pragma warning disable EF1001 // Internal EF Core API usage.
LiftableConstantExpressionHelpers.BuildClrCollectionAccessorLambda(navigation),
#pragma warning restore EF1001 // Internal EF Core API usage.
navigation.Name + "ClrCollectionAccessor",
typeof(IClrCollectionAccessor)),
CollectionAccessorAddMethodInfo,
entity,
relatedEntity,
Expand Down
Loading

0 comments on commit 3a7faf7

Please # to comment.