|
|
@ -14,24 +14,24 @@ public unsafe class IterActionGenerator |
|
|
|
{ |
|
|
|
{ |
|
|
|
private static readonly ConstructorInfo _entityRefCtor = typeof(EntityRef).GetConstructors().Single(); |
|
|
|
private static readonly ConstructorInfo _entityRefCtor = typeof(EntityRef).GetConstructors().Single(); |
|
|
|
|
|
|
|
|
|
|
|
private static readonly PropertyInfo _iteratorWorldProp = typeof(Iterator).GetProperty(nameof(Iterator.World))!; |
|
|
|
private static readonly PropertyInfo _iterWorldProp = typeof(Iterator).GetProperty(nameof(Iterator.World))!; |
|
|
|
private static readonly PropertyInfo _iteratorDeltaTimeProp = typeof(Iterator).GetProperty(nameof(Iterator.DeltaTime))!; |
|
|
|
private static readonly PropertyInfo _iterDeltaTimeProp = typeof(Iterator).GetProperty(nameof(Iterator.DeltaTime))!; |
|
|
|
private static readonly PropertyInfo _iteratorCountProp = typeof(Iterator).GetProperty(nameof(Iterator.Count))!; |
|
|
|
private static readonly PropertyInfo _iterCountProp = typeof(Iterator).GetProperty(nameof(Iterator.Count))!; |
|
|
|
private static readonly MethodInfo _iteratorEntityMethod = typeof(Iterator).GetMethod(nameof(Iterator.Entity))!; |
|
|
|
private static readonly MethodInfo _iterEntityMethod = typeof(Iterator).GetMethod(nameof(Iterator.Entity))!; |
|
|
|
private static readonly MethodInfo _iteratorFieldMethod = typeof(Iterator).GetMethod(nameof(Iterator.Field))!; |
|
|
|
private static readonly MethodInfo _iterFieldMethod = typeof(Iterator).GetMethod(nameof(Iterator.Field ), 1, new[] { typeof(int) })!; |
|
|
|
private static readonly MethodInfo _iteratorFieldOrEmptyMethod = typeof(Iterator).GetMethod(nameof(Iterator.FieldOrEmpty))!; |
|
|
|
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 PropertyInfo _handleTargetProp = typeof(ReferenceHandle).GetProperty(nameof(ReferenceHandle.Target))!; |
|
|
|
private static readonly MethodInfo _iterFieldOrEmptyRefMethod = typeof(Iterator).GetMethod(nameof(Iterator.FieldOrEmpty), 1, new[] { typeof(int), Type.MakeGenericMethodParameter(0) })!; |
|
|
|
|
|
|
|
|
|
|
|
private static readonly ConditionalWeakTable<MethodInfo, IterActionGenerator> _cache = new(); |
|
|
|
private static readonly ConditionalWeakTable<MethodInfo, IterActionGenerator> _cache = new(); |
|
|
|
private static readonly Dictionary<Type, Action<ILGeneratorWrapper, IArgument<Iterator>>> _globalUniqueParameters = new() { |
|
|
|
private static readonly Dictionary<Type, Action<ILGeneratorWrapper, IArgument<Iterator>>> _globalUniqueParameters = new() { |
|
|
|
[typeof(World)] = (IL, iter) => { IL.Load(iter, _iteratorWorldProp); }, |
|
|
|
[typeof(World)] = (IL, iter) => { IL.Load(iter, _iterWorldProp); }, |
|
|
|
[typeof(Universe)] = (IL, iter) => { IL.Load(iter, _iteratorWorldProp); IL.Cast(typeof(Universe)); }, |
|
|
|
[typeof(Universe)] = (IL, iter) => { IL.Load(iter, _iterWorldProp); IL.Cast(typeof(Universe)); }, |
|
|
|
[typeof(TimeSpan)] = (IL, iter) => { IL.Load(iter, _iteratorDeltaTimeProp); }, |
|
|
|
[typeof(TimeSpan)] = (IL, iter) => { IL.Load(iter, _iterDeltaTimeProp); }, |
|
|
|
}; |
|
|
|
}; |
|
|
|
private static readonly Dictionary<Type, Action<ILGeneratorWrapper, IArgument<Iterator>, ILocal<int>>> _uniqueParameters = new() { |
|
|
|
private static readonly Dictionary<Type, Action<ILGeneratorWrapper, IArgument<Iterator>, ILocal<int>>> _uniqueParameters = new() { |
|
|
|
[typeof(Iterator)] = (IL, iter, i) => { IL.Load(iter); }, |
|
|
|
[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; } |
|
|
|
public World World { get; } |
|
|
@ -110,7 +110,7 @@ public unsafe class IterActionGenerator |
|
|
|
fieldLocal = IL.Local(spanType, $"{p.Info.Name}Field"); |
|
|
|
fieldLocal = IL.Local(spanType, $"{p.Info.Name}Field"); |
|
|
|
IL.Load(iteratorArg); |
|
|
|
IL.Load(iteratorArg); |
|
|
|
IL.LoadConst(fieldIndex); |
|
|
|
IL.LoadConst(fieldIndex); |
|
|
|
IL.Call(_iteratorFieldOrEmptyMethod.MakeGenericMethod(p.FieldType)); |
|
|
|
IL.Call(_iterFieldOrEmptyMethod.MakeGenericMethod(p.FieldType)); |
|
|
|
IL.Store(fieldLocal); |
|
|
|
IL.Store(fieldLocal); |
|
|
|
|
|
|
|
|
|
|
|
if (p.UnderlyingType.IsValueType) { |
|
|
|
if (p.UnderlyingType.IsValueType) { |
|
|
@ -126,7 +126,7 @@ public unsafe class IterActionGenerator |
|
|
|
fieldLocal = IL.Local(spanType, $"{p.Info.Name}Field"); |
|
|
|
fieldLocal = IL.Local(spanType, $"{p.Info.Name}Field"); |
|
|
|
IL.Load(iteratorArg); |
|
|
|
IL.Load(iteratorArg); |
|
|
|
IL.LoadConst(fieldIndex); |
|
|
|
IL.LoadConst(fieldIndex); |
|
|
|
IL.Call(_iteratorFieldMethod.MakeGenericMethod(p.FieldType)); |
|
|
|
IL.Call(_iterFieldMethod.MakeGenericMethod(p.FieldType)); |
|
|
|
IL.Store(fieldLocal); |
|
|
|
IL.Store(fieldLocal); |
|
|
|
break; |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
@ -134,17 +134,11 @@ public unsafe class IterActionGenerator |
|
|
|
paramData.Add((p, term, fieldLocal, tempLocal)); |
|
|
|
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<ReferenceHandle>() : null; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
var indexLocal = IL.Local<int>("iter_index"); |
|
|
|
var indexLocal = IL.Local<int>("iter_index"); |
|
|
|
var countLocal = IL.Local<int>("iter_count"); |
|
|
|
var countLocal = IL.Local<int>("iter_count"); |
|
|
|
|
|
|
|
|
|
|
|
IL.Set(indexLocal, 0); |
|
|
|
IL.Set(indexLocal, 0); |
|
|
|
IL.Load(iteratorArg, _iteratorCountProp); |
|
|
|
IL.Load(iteratorArg, _iterCountProp); |
|
|
|
IL.Store(countLocal); |
|
|
|
IL.Store(countLocal); |
|
|
|
|
|
|
|
|
|
|
|
// If all parameters are fixed, iterator count will be 0, but since |
|
|
|
// If all parameters are fixed, iterator count will be 0, but since |
|
|
@ -186,9 +180,10 @@ public unsafe class IterActionGenerator |
|
|
|
break; |
|
|
|
break; |
|
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
default: |
|
|
|
var spanType = typeof(Span<>).MakeGenericType(info.FieldType); |
|
|
|
var spanType = isValueType ? typeof(Span<>) : typeof(Iterator.SpanToRef<>); |
|
|
|
var spanItemMethod = spanType.GetProperty("Item")!.GetMethod!; |
|
|
|
var concreteSpanType = spanType.MakeGenericType(info.UnderlyingType); |
|
|
|
var spanLengthMethod = spanType.GetProperty("Length")!.GetMethod!; |
|
|
|
var spanItemMethod = concreteSpanType.GetProperty("Item")!.GetMethod!; |
|
|
|
|
|
|
|
var spanLengthMethod = concreteSpanType.GetProperty("Length")!.GetMethod!; |
|
|
|
|
|
|
|
|
|
|
|
IL.Comment($"Parameter {paramName}"); |
|
|
|
IL.Comment($"Parameter {paramName}"); |
|
|
|
if (info.IsByRef) { |
|
|
|
if (info.IsByRef) { |
|
|
@ -201,15 +196,7 @@ public unsafe class IterActionGenerator |
|
|
|
if (info.IsFixed) IL.LoadConst(0); |
|
|
|
if (info.IsFixed) IL.LoadConst(0); |
|
|
|
else IL.Load(indexLocal!); |
|
|
|
else IL.Load(indexLocal!); |
|
|
|
IL.Call(spanItemMethod); |
|
|
|
IL.Call(spanItemMethod); |
|
|
|
IL.LoadObj(info.FieldType); |
|
|
|
if (isValueType) 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 { |
|
|
|
} else { |
|
|
|
var elseLabel = IL.DefineLabel(); |
|
|
|
var elseLabel = IL.DefineLabel(); |
|
|
|
var doneLabel = IL.DefineLabel(); |
|
|
|
var doneLabel = IL.DefineLabel(); |
|
|
@ -220,18 +207,14 @@ public unsafe class IterActionGenerator |
|
|
|
if (info.IsFixed) IL.LoadConst(0); |
|
|
|
if (info.IsFixed) IL.LoadConst(0); |
|
|
|
else IL.Load(indexLocal!); |
|
|
|
else IL.Load(indexLocal!); |
|
|
|
IL.Call(spanItemMethod); |
|
|
|
IL.Call(spanItemMethod); |
|
|
|
|
|
|
|
if (isValueType) { |
|
|
|
IL.LoadObj(info.FieldType); |
|
|
|
IL.LoadObj(info.FieldType); |
|
|
|
if (!isValueType) { |
|
|
|
IL.New(info.ParameterType); |
|
|
|
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); |
|
|
|
|
|
|
|
IL.Goto(doneLabel); |
|
|
|
IL.Goto(doneLabel); |
|
|
|
IL.MarkLabel(elseLabel); |
|
|
|
IL.MarkLabel(elseLabel); |
|
|
|
if (!isValueType) IL.LoadNull(); |
|
|
|
if (isValueType) IL.LoadObj(tempLocal!); |
|
|
|
else IL.LoadObj(tempLocal!); |
|
|
|
else IL.LoadNull(); |
|
|
|
IL.MarkLabel(doneLabel); |
|
|
|
IL.MarkLabel(doneLabel); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
break; |
|
|
|