From 6eb1ef0de96123180c0c0d1a0d32513711422008 Mon Sep 17 00:00:00 2001 From: copygirl Date: Sat, 31 Dec 2022 01:38:34 +0100 Subject: [PATCH] Use SpanToRef in IterActionGenerator --- .../Utility/IL/IterActionGenerator.cs | 69 +++++++------------ 1 file changed, 26 insertions(+), 43 deletions(-) diff --git a/src/gaemstone/Utility/IL/IterActionGenerator.cs b/src/gaemstone/Utility/IL/IterActionGenerator.cs index 254a629..2815ab6 100644 --- a/src/gaemstone/Utility/IL/IterActionGenerator.cs +++ b/src/gaemstone/Utility/IL/IterActionGenerator.cs @@ -14,24 +14,24 @@ public unsafe class IterActionGenerator { private static readonly ConstructorInfo _entityRefCtor = typeof(EntityRef).GetConstructors().Single(); - private static readonly PropertyInfo _iteratorWorldProp = typeof(Iterator).GetProperty(nameof(Iterator.World))!; - private static readonly PropertyInfo _iteratorDeltaTimeProp = typeof(Iterator).GetProperty(nameof(Iterator.DeltaTime))!; - private static readonly PropertyInfo _iteratorCountProp = typeof(Iterator).GetProperty(nameof(Iterator.Count))!; - private static readonly MethodInfo _iteratorEntityMethod = typeof(Iterator).GetMethod(nameof(Iterator.Entity))!; - private static readonly MethodInfo _iteratorFieldMethod = typeof(Iterator).GetMethod(nameof(Iterator.Field))!; - private static readonly MethodInfo _iteratorFieldOrEmptyMethod = typeof(Iterator).GetMethod(nameof(Iterator.FieldOrEmpty))!; - - private static readonly PropertyInfo _handleTargetProp = typeof(ReferenceHandle).GetProperty(nameof(ReferenceHandle.Target))!; + private static readonly PropertyInfo _iterWorldProp = typeof(Iterator).GetProperty(nameof(Iterator.World))!; + private static readonly PropertyInfo _iterDeltaTimeProp = typeof(Iterator).GetProperty(nameof(Iterator.DeltaTime))!; + private static readonly PropertyInfo _iterCountProp = typeof(Iterator).GetProperty(nameof(Iterator.Count))!; + private static readonly MethodInfo _iterEntityMethod = typeof(Iterator).GetMethod(nameof(Iterator.Entity))!; + private static readonly MethodInfo _iterFieldMethod = typeof(Iterator).GetMethod(nameof(Iterator.Field ), 1, new[] { typeof(int) })!; + private static readonly MethodInfo _iterFieldOrEmptyMethod = typeof(Iterator).GetMethod(nameof(Iterator.FieldOrEmpty), 1, new[] { typeof(int) })!; + private static readonly MethodInfo _iterFieldRefMethod = typeof(Iterator).GetMethod(nameof(Iterator.Field ), 1, new[] { typeof(int), Type.MakeGenericMethodParameter(0) })!; + private static readonly MethodInfo _iterFieldOrEmptyRefMethod = typeof(Iterator).GetMethod(nameof(Iterator.FieldOrEmpty), 1, new[] { typeof(int), Type.MakeGenericMethodParameter(0) })!; private static readonly ConditionalWeakTable _cache = new(); private static readonly Dictionary>> _globalUniqueParameters = new() { - [typeof(World)] = (IL, iter) => { IL.Load(iter, _iteratorWorldProp); }, - [typeof(Universe)] = (IL, iter) => { IL.Load(iter, _iteratorWorldProp); IL.Cast(typeof(Universe)); }, - [typeof(TimeSpan)] = (IL, iter) => { IL.Load(iter, _iteratorDeltaTimeProp); }, + [typeof(World)] = (IL, iter) => { IL.Load(iter, _iterWorldProp); }, + [typeof(Universe)] = (IL, iter) => { IL.Load(iter, _iterWorldProp); IL.Cast(typeof(Universe)); }, + [typeof(TimeSpan)] = (IL, iter) => { IL.Load(iter, _iterDeltaTimeProp); }, }; private static readonly Dictionary, ILocal>> _uniqueParameters = new() { [typeof(Iterator)] = (IL, iter, i) => { IL.Load(iter); }, - [typeof(EntityRef)] = (IL, iter, i) => { IL.Load(iter); IL.Load(i); IL.Call(_iteratorEntityMethod); }, + [typeof(EntityRef)] = (IL, iter, i) => { IL.Load(iter); IL.Load(i); IL.Call(_iterEntityMethod); }, }; public World World { get; } @@ -110,7 +110,7 @@ public unsafe class IterActionGenerator fieldLocal = IL.Local(spanType, $"{p.Info.Name}Field"); IL.Load(iteratorArg); IL.LoadConst(fieldIndex); - IL.Call(_iteratorFieldOrEmptyMethod.MakeGenericMethod(p.FieldType)); + IL.Call(_iterFieldOrEmptyMethod.MakeGenericMethod(p.FieldType)); IL.Store(fieldLocal); if (p.UnderlyingType.IsValueType) { @@ -126,7 +126,7 @@ public unsafe class IterActionGenerator fieldLocal = IL.Local(spanType, $"{p.Info.Name}Field"); IL.Load(iteratorArg); IL.LoadConst(fieldIndex); - IL.Call(_iteratorFieldMethod.MakeGenericMethod(p.FieldType)); + IL.Call(_iterFieldMethod.MakeGenericMethod(p.FieldType)); IL.Store(fieldLocal); break; } @@ -134,17 +134,11 @@ public unsafe class IterActionGenerator paramData.Add((p, term, fieldLocal, tempLocal)); } - // If there's any reference type parameters, we need to define a ReferenceHandle local. - var hasReferenceType = paramData - .Where(p => p.Info.Kind > ParamKind.Unique) - .Any(p => !p.Info.UnderlyingType.IsValueType); - var handleLocal = hasReferenceType ? IL.Local() : null; - var indexLocal = IL.Local("iter_index"); var countLocal = IL.Local("iter_count"); IL.Set(indexLocal, 0); - IL.Load(iteratorArg, _iteratorCountProp); + IL.Load(iteratorArg, _iterCountProp); IL.Store(countLocal); // If all parameters are fixed, iterator count will be 0, but since @@ -186,9 +180,10 @@ public unsafe class IterActionGenerator break; default: - var spanType = typeof(Span<>).MakeGenericType(info.FieldType); - var spanItemMethod = spanType.GetProperty("Item")!.GetMethod!; - var spanLengthMethod = spanType.GetProperty("Length")!.GetMethod!; + var spanType = isValueType ? typeof(Span<>) : typeof(Iterator.SpanToRef<>); + var concreteSpanType = spanType.MakeGenericType(info.UnderlyingType); + var spanItemMethod = concreteSpanType.GetProperty("Item")!.GetMethod!; + var spanLengthMethod = concreteSpanType.GetProperty("Length")!.GetMethod!; IL.Comment($"Parameter {paramName}"); if (info.IsByRef) { @@ -201,15 +196,7 @@ public unsafe class IterActionGenerator if (info.IsFixed) IL.LoadConst(0); else IL.Load(indexLocal!); IL.Call(spanItemMethod); - IL.LoadObj(info.FieldType); - - if (!isValueType) { - IL.Comment($"Convert ReferenceHandle to {paramName}"); - IL.Store(handleLocal!); - IL.LoadAddr(handleLocal!); - IL.Call(_handleTargetProp.GetMethod!); - IL.Cast(info.UnderlyingType); - } + if (isValueType) IL.LoadObj(info.FieldType); } else { var elseLabel = IL.DefineLabel(); var doneLabel = IL.DefineLabel(); @@ -220,18 +207,14 @@ public unsafe class IterActionGenerator if (info.IsFixed) IL.LoadConst(0); else IL.Load(indexLocal!); IL.Call(spanItemMethod); - IL.LoadObj(info.FieldType); - if (!isValueType) { - IL.Comment($"Convert ReferenceHandle to {paramName}"); - IL.Store(handleLocal!); - IL.LoadAddr(handleLocal!); - IL.Call(_handleTargetProp.GetMethod!); - IL.Cast(info.UnderlyingType); - } else IL.New(info.ParameterType); + if (isValueType) { + IL.LoadObj(info.FieldType); + IL.New(info.ParameterType); + } IL.Goto(doneLabel); IL.MarkLabel(elseLabel); - if (!isValueType) IL.LoadNull(); - else IL.LoadObj(tempLocal!); + if (isValueType) IL.LoadObj(tempLocal!); + else IL.LoadNull(); IL.MarkLabel(doneLabel); } break;