Skip to content

Commit 6673d51

Browse files
authored
Merge pull request #190 from servicetitan/upstream/MakeGenericMethod
Memoize MakeGenericMethod(), MakeGenericType() methods (#50)
2 parents 9498343 + 71d4a82 commit 6673d51

40 files changed

Lines changed: 220 additions & 139 deletions

Extensions/Xtensive.Orm.BulkOperations/Internals/ExpressionExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2019-2020 Xtensive LLC.
1+
// Copyright (C) 2019-2020 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44

@@ -29,7 +29,7 @@ public static bool IsContainsQuery(this Expression expression)
2929
internal static object Invoke(this Expression expression)
3030
{
3131
return FastExpression.Lambda(
32-
WellKnownMembers.FuncOfTResultType.MakeGenericType(expression.Type), expression).Compile().DynamicInvoke();
32+
WellKnownMembers.FuncOfTResultType.CachedMakeGenericType(expression.Type), expression).Compile().DynamicInvoke();
3333
}
3434

3535
internal static Expression Visit<T>(this Expression exp, Func<T, Expression> visitor) where T : Expression

Extensions/Xtensive.Orm.BulkOperations/Internals/Operation.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2019-2021 Xtensive LLC.
1+
// Copyright (C) 2019-2020 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44

@@ -11,6 +11,7 @@
1111
using Xtensive.Orm.Linq;
1212
using Xtensive.Orm.Providers;
1313
using Xtensive.Orm.Services;
14+
using Xtensive.Reflection;
1415
using Xtensive.Sql;
1516
using Xtensive.Sql.Dml;
1617
using QueryParameterBinding = Xtensive.Orm.Services.QueryParameterBinding;
@@ -68,7 +69,7 @@ protected void EnsureTransactionIsStarted()
6869

6970
public QueryTranslationResult GetRequest(Type type, IQueryable query)
7071
{
71-
var translateQueryMethod = WellKnownMembers.TranslateQueryMethod.MakeGenericMethod(type);
72+
var translateQueryMethod = WellKnownMembers.TranslateQueryMethod.CachedMakeGenericMethod(type);
7273
return (QueryTranslationResult) translateQueryMethod.Invoke(QueryBuilder, new object[] {query});
7374
}
7475

Extensions/Xtensive.Orm.BulkOperations/Internals/QueryOperation.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Xtensive.Core;
1010
using Xtensive.Orm.Linq;
1111
using Xtensive.Orm.Model;
12+
using Xtensive.Reflection;
1213
using Xtensive.Sql;
1314
using Xtensive.Sql.Dml;
1415

@@ -35,7 +36,7 @@ protected override int ExecuteInternal()
3536
ex.Arguments.Count == 2) {
3637
var localCollection = ex.Arguments[0];//IEnumerable<T>
3738
var valueToCheck = ex.Arguments[1];
38-
var genericInMethod = WellKnownMembers.InMethod.MakeGenericMethod(new[] { valueToCheck.Type });
39+
var genericInMethod = WellKnownMembers.InMethod.CachedMakeGenericMethod(valueToCheck.Type);
3940
ex = Expression.Call(genericInMethod, valueToCheck, Expression.Constant(IncludeAlgorithm.ComplexCondition), localCollection);
4041
methodInfo = ex.Method;
4142
}

Extensions/Xtensive.Orm.BulkOperations/Internals/SetOperation.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using Xtensive.Sql.Dml;
1313
using Xtensive.Core;
1414
using Xtensive.Linq;
15+
using Xtensive.Reflection;
1516

1617
namespace Xtensive.Orm.BulkOperations
1718
{
@@ -205,7 +206,7 @@ private void AddEntityValue(AddValueContext addContext)
205206
ParameterExpression p = Expression.Parameter(info.UnderlyingType);
206207
LambdaExpression lambda =
207208
FastExpression.Lambda(
208-
WellKnownMembers.FuncOfTArgTResultType.MakeGenericType(info.UnderlyingType, field.ValueType),
209+
WellKnownMembers.FuncOfTArgTResultType.CachedMakeGenericType(info.UnderlyingType, field.ValueType),
209210
Expression.MakeMemberAccess(p, field.UnderlyingProperty),
210211
p);
211212
IQueryable q =
@@ -244,7 +245,7 @@ public void AddValues()
244245
Descriptor = descriptor,
245246
Lambda =
246247
FastExpression.Lambda(
247-
WellKnownMembers.FuncOfTArgTResultType.MakeGenericType(typeof (T), descriptor.Expression.Type),
248+
WellKnownMembers.FuncOfTArgTResultType.CachedMakeGenericType(typeof (T), descriptor.Expression.Type),
248249
descriptor.Expression,
249250
descriptor.Parameter),
250251
Statement = Statement

Orm/Xtensive.Orm/Linq/ExpressionExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ static ExpressionExtensions()
7979
{
8080
var tupleGenericAccessor = WellKnownOrmTypes.Tuple.GetMethods()
8181
.Single(mi => mi.Name == nameof(Tuple.GetValueOrDefault) && mi.IsGenericMethod);
82-
TupleValueAccessorFactory = type => tupleGenericAccessor.MakeGenericMethod(type);
82+
TupleValueAccessorFactory = type => tupleGenericAccessor.CachedMakeGenericMethod(type);
8383
}
8484
}
8585
}

Orm/Xtensive.Orm/Linq/Internals/LambdaExpressionFactory.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,14 +74,14 @@ public LambdaExpression CreateLambda(Expression body, ParameterExpression[] para
7474
internal Factory CreateFactorySlow(Type delegateType)
7575
{
7676
var factory = (SlowFactory) Delegate.CreateDelegate(
77-
SlowFactoryType, slowFactoryMethod.MakeGenericMethod(delegateType));
77+
SlowFactoryType, slowFactoryMethod.CachedMakeGenericMethod(delegateType));
7878

7979
return (body, parameters) => factory.Invoke(body, parameters);
8080
}
8181

8282
internal static Factory CreateFactoryFast(Type delegateType)
8383
{
84-
var method = WellKnownTypes.ExpressionOfT.MakeGenericType(delegateType).GetMethod(
84+
var method = WellKnownTypes.ExpressionOfT.CachedMakeGenericType(delegateType).GetMethod(
8585
"Create", BindingFlags.Static | BindingFlags.NonPublic, null, internalFactorySignature, null);
8686

8787
if (method == null) {

Orm/Xtensive.Orm/Modelling/PropertyAccessor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ private void Initialize()
175175
compareCaseInsensitive = tProperty == WellKnownTypes.String && pa.CaseInsensitiveComparison;
176176
}
177177
InnerInitializeMethodDefinition
178-
.MakeGenericMethod(new[] {tType, tProperty})
178+
.CachedMakeGenericMethod(tType, tProperty)
179179
.Invoke(this, null);
180180
}
181181

Orm/Xtensive.Orm/Orm/Building/Builders/KeyGeneratorFactory.cs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2012-2020 Xtensive LLC.
1+
// Copyright (C) 2012-2020 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44
// Created by: Denis Krjuchkov
@@ -31,22 +31,28 @@ internal static class KeyGeneratorFactory
3131
.Concat(new[] { WellKnownTypes.Guid, WellKnownTypes.String })
3232
.ToArray();
3333

34+
private static readonly Type
35+
StorageSequentalGeneratorType = typeof(StorageSequentalGenerator<>),
36+
TemporarySequentalGeneratorType = typeof(TemporarySequentalGenerator<>),
37+
GuidGeneratorType = typeof(GuidGenerator),
38+
StringGeneratorType = typeof(StringGenerator);
39+
3440
public static bool IsSupported(Type valueType) => SupportedTypes.Contains(valueType);
3541

3642
public static bool IsSequenceBacked(Type valueType) => SupportedNumericTypes.Contains(valueType);
3743

3844
private static Type GetGeneratorType(Type valueType)
3945
{
4046
if (IsSequenceBacked(valueType)) {
41-
return typeof(StorageSequentalGenerator<>).MakeGenericType(valueType);
47+
return StorageSequentalGeneratorType.CachedMakeGenericType(valueType);
4248
}
4349

4450
if (valueType == WellKnownTypes.Guid) {
45-
return typeof(GuidGenerator);
51+
return GuidGeneratorType;
4652
}
4753

4854
if (valueType == WellKnownTypes.String) {
49-
return typeof(StringGenerator);
55+
return StringGeneratorType;
5056
}
5157

5258
throw TypeNotSupported(valueType);
@@ -55,15 +61,15 @@ private static Type GetGeneratorType(Type valueType)
5561
private static Type GetTemporaryGeneratorType(Type valueType)
5662
{
5763
if (IsSequenceBacked(valueType)) {
58-
return typeof(TemporarySequentalGenerator<>).MakeGenericType(valueType);
64+
return TemporarySequentalGeneratorType.CachedMakeGenericType(valueType);
5965
}
6066

6167
if (valueType == WellKnownTypes.Guid) {
62-
return typeof(GuidGenerator);
68+
return GuidGeneratorType;
6369
}
6470

6571
if (valueType == WellKnownTypes.String) {
66-
return typeof(StringGenerator);
72+
return StringGeneratorType;
6773
}
6874

6975
throw TypeNotSupported(valueType);

Orm/Xtensive.Orm/Orm/Building/Builders/ModelBuilder.cs

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// Created: 2007.09.26
66

77
using System;
8+
using System.Collections.Concurrent;
89
using System.Collections.Generic;
910
using System.Linq;
1011
using System.Reflection;
@@ -26,7 +27,33 @@ internal sealed class ModelBuilder
2627
{
2728
private const string GeneratedTypeNameFormat = "{0}.EntitySetItems.{1}";
2829

29-
private static ThreadSafeDictionary<string, Type> GeneratedTypes = ThreadSafeDictionary<string, Type>.Create(new object());
30+
private readonly struct TypeKey : IEquatable<TypeKey>
31+
{
32+
public readonly string Name;
33+
public readonly Type OwnerType;
34+
public readonly Type TargetType;
35+
36+
public bool Equals(TypeKey other) => string.Equals(Name, other.Name);
37+
38+
public override bool Equals(object obj) => obj is TypeKey other && Equals(other);
39+
40+
public override int GetHashCode() => (Name ?? string.Empty).GetHashCode();
41+
42+
public TypeKey(string name, Type ownerType, Type targetType)
43+
{
44+
Name = name;
45+
OwnerType = ownerType;
46+
TargetType = targetType;
47+
}
48+
}
49+
50+
private static readonly ConcurrentDictionary<TypeKey, Lazy<Type>> GeneratedTypes = new ConcurrentDictionary<TypeKey, Lazy<Type>>();
51+
52+
private static readonly Func<TypeKey, Lazy<Type>> AuxiliaryTypeFactory = typeKey =>
53+
new Lazy<Type>(() => {
54+
var baseType = WellKnownOrmTypes.EntitySetItemOfT1T2.CachedMakeGenericType(typeKey.OwnerType, typeKey.TargetType);
55+
return TypeHelper.CreateInheritedDummyType(typeKey.Name, baseType, true);
56+
});
3057

3158
private readonly BuildingContext context;
3259
private readonly TypeBuilder typeBuilder;
@@ -403,20 +430,14 @@ private void BuildAuxiliaryTypes(IEnumerable<AssociationInfo> associations)
403430

404431
private Type GenerateAuxiliaryType(AssociationInfo association)
405432
{
406-
var masterType = association.OwnerType.UnderlyingType;
407-
var slaveType = association.TargetType.UnderlyingType;
408-
var baseType = WellKnownOrmTypes.EntitySetItemOfT1T2.MakeGenericType(masterType, slaveType);
433+
var ownerType = association.OwnerType.UnderlyingType;
434+
var targetType = association.TargetType.UnderlyingType;
409435

410436
var typeName = string.Format(GeneratedTypeNameFormat,
411-
masterType.Namespace,
437+
ownerType.Namespace,
412438
context.NameBuilder.BuildAssociationName(association));
413439

414-
var result = GeneratedTypes.GetValue(typeName,
415-
(_typeName, _baseType) =>
416-
TypeHelper.CreateInheritedDummyType(_typeName, _baseType, true),
417-
baseType);
418-
419-
return result;
440+
return GeneratedTypes.GetOrAdd(new TypeKey(typeName, ownerType, targetType), AuxiliaryTypeFactory).Value;
420441
}
421442

422443
private void FindAndMarkInboundAndOutboundTypes(BuildingContext context)

Orm/Xtensive.Orm/Orm/Building/Builders/PartialIndexFilterBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ private Expression BuildFieldAccess(FieldInfo field, bool addNullability)
113113
var valueType = addNullability ? field.ValueType.ToNullable() : field.ValueType;
114114
usedFields.Add(field);
115115
return Expression.Call(Parameter,
116-
WellKnownMembers.Tuple.GenericAccessor.MakeGenericMethod(valueType),
116+
WellKnownMembers.Tuple.GenericAccessor.CachedMakeGenericMethod(valueType),
117117
Expression.Constant(fieldIndex));
118118
}
119119

0 commit comments

Comments
 (0)