using System; using System.Collections.Generic; namespace Burst.Compiler.IL.Tests { /// /// This class provides a delegate for each test methods that should have been pre-generated by /// when running the tests locally. /// /// NOTE: This code is a **SUPER LABORIOUS** workaround a bug in mono 5.11 that is preventing us from dynamically calling a delegate /// to native code through Delegate DynamicInvoke. /// /// On .NET Framework and newer version of mono, we would not need this, so we are going to keep this code around until /// mono is entirely upgraded in Unity. /// internal static partial class StaticDelegateRegistry { private static readonly Dictionary RegisteredDelegateTypes = new Dictionary(); private static void Register(Type returnType, Type[] arguments, Type typeDelegate, Func caller) { if (returnType == null) throw new ArgumentNullException(nameof(returnType)); if (arguments == null) throw new ArgumentNullException(nameof(arguments)); if (typeDelegate == null) throw new ArgumentNullException(nameof(typeDelegate)); // don't clone as we have the guarantee that it is generated internally RegisteredDelegateTypes.Add(new SignatureKey(returnType, arguments), new StaticDelegateCallback(typeDelegate, caller)); } public static bool Contains(Type returnType, Type[] arguments) { if (returnType == null) throw new ArgumentNullException(nameof(returnType)); if (arguments == null) throw new ArgumentNullException(nameof(arguments)); return RegisteredDelegateTypes.ContainsKey(new SignatureKey(returnType, arguments)); } public static bool TryFind(Type returnType, Type[] arguments, out StaticDelegateCallback staticDelegate) { if (returnType == null) throw new ArgumentNullException(nameof(returnType)); if (arguments == null) throw new ArgumentNullException(nameof(arguments)); return RegisteredDelegateTypes.TryGetValue(new SignatureKey(returnType, (Type[])arguments.Clone()), out staticDelegate); } internal struct SignatureKey : IEquatable { public SignatureKey(Type returnType, Type[] parameterTypes) { ReturnType = returnType; ParameterTypes = parameterTypes; } public readonly Type ReturnType; public readonly Type[] ParameterTypes; public bool Equals(SignatureKey other) { if (ParameterTypes.Length != other.ParameterTypes.Length) return false; if (ReturnType != other.ReturnType) return false; for (int i = 0; i < ParameterTypes.Length; i++) { var arg = ParameterTypes[i]; var otherArg = other.ParameterTypes[i]; if (arg != otherArg) return false; } return true; } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; return obj is SignatureKey other && Equals(other); } public override int GetHashCode() { unchecked { var hashcode = ReturnType.GetHashCode(); for (int i = 0; i < ParameterTypes.Length; i++) { hashcode = (hashcode * 397) ^ ParameterTypes[i].GetHashCode(); } return hashcode; } } public static bool operator ==(SignatureKey left, SignatureKey right) { return left.Equals(right); } public static bool operator !=(SignatureKey left, SignatureKey right) { return !left.Equals(right); } } } internal struct StaticDelegateCallback { public StaticDelegateCallback(Type delegateType, Func caller) { DelegateType = delegateType; Caller = caller; } public readonly Type DelegateType; public readonly Func Caller; } }