From c76e68411fbbd7cc68970d4c921ea48e4c2c7941 Mon Sep 17 00:00:00 2001 From: walon Date: Fri, 23 Sep 2022 15:16:43 +0800 Subject: [PATCH] =?UTF-8?q?[new]=20AOTGenericReferences=E6=89=93=E5=8D=B0?= =?UTF-8?q?=E5=87=BA=E8=AF=A6=E7=BB=86=E7=9A=84=E6=B3=9B=E5=9E=8B=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E5=8F=8A=E5=87=BD=E6=95=B0=E7=AD=BE=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Editor/AOT/Analyzer.cs | 4 ++- Editor/AOT/ConstraintContext.cs | 53 +++++++++++++++++++++++++++- Editor/AOT/GenericReferenceWriter.cs | 14 ++++++-- Editor/EqualityUtil.cs | 13 +++++++ Editor/Meta/GenericClass.cs | 5 +++ Editor/Meta/GenericMethod.cs | 8 +++++ 6 files changed, 93 insertions(+), 4 deletions(-) diff --git a/Editor/AOT/Analyzer.cs b/Editor/AOT/Analyzer.cs index 331422d..ea446e2 100644 --- a/Editor/AOT/Analyzer.cs +++ b/Editor/AOT/Analyzer.cs @@ -37,6 +37,8 @@ namespace HybridCLR.Editor.AOT private readonly HashSet _hotUpdateAssemblyFiles; + public ConstraintContext ConstraintContext { get; } = new ConstraintContext(); + public List AotGenericTypes { get; } = new List(); public List AotGenericMethods { get; } = new List(); @@ -195,7 +197,7 @@ namespace HybridCLR.Editor.AOT private void FilterAOTGenericTypeAndMethods() { - var cc = new ConstraintContext(); + ConstraintContext cc = this.ConstraintContext; AotGenericTypes.AddRange(_genericTypes.Where(type => IsAotType(type.Type)).Select(gc => cc.ApplyConstraints(gc))); AotGenericMethods.AddRange(_genericMethods.Where(method => IsAotGenericMethod(method.Method)).Select(gm => cc.ApplyConstraints(gm))); } diff --git a/Editor/AOT/ConstraintContext.cs b/Editor/AOT/ConstraintContext.cs index 0a9a7fc..82477e1 100644 --- a/Editor/AOT/ConstraintContext.cs +++ b/Editor/AOT/ConstraintContext.cs @@ -1,4 +1,5 @@ -using HybridCLR.Editor.Meta; +using dnlib.DotNet; +using HybridCLR.Editor.Meta; using System; using System.Collections.Generic; using System.Linq; @@ -7,8 +8,58 @@ using System.Threading.Tasks; namespace HybridCLR.Editor.AOT { + public class ConstraintContext { + public class ImplType + { + public TypeSig BaseType { get; } + + public List Interfaces { get; } + + public bool ValueType { get; } + + private readonly int _hash; + + public ImplType(TypeSig baseType, List interfaces, bool valueType) + { + BaseType = baseType; + Interfaces = interfaces; + ValueType = valueType; + _hash = ComputHash(); + } + + public override bool Equals(object obj) + { + ImplType o = (ImplType)obj; + return EqualityUtil.EqualsTypeSig(this.BaseType, o.BaseType) + && EqualityUtil.EqualsTypeSigArray(this.Interfaces, o.Interfaces) + && this.ValueType == o.ValueType; + } + + public override int GetHashCode() + { + return _hash; + } + + private int ComputHash() + { + int hash = 0; + if (BaseType != null) + { + hash = HashUtil.CombineHash(hash, TypeEqualityComparer.Instance.GetHashCode(BaseType)); + } + if (Interfaces.Count > 0) + { + hash = HashUtil.CombineHash(hash, HashUtil.ComputHash(Interfaces)); + } + + return hash; + } + } + + public HashSet ImplTypes { get; } = new HashSet(); + public GenericClass ApplyConstraints(GenericClass gc) { return gc; diff --git a/Editor/AOT/GenericReferenceWriter.cs b/Editor/AOT/GenericReferenceWriter.cs index 7fd30e1..89d337a 100644 --- a/Editor/AOT/GenericReferenceWriter.cs +++ b/Editor/AOT/GenericReferenceWriter.cs @@ -20,18 +20,28 @@ namespace HybridCLR.Editor.AOT codes.Add("public class AOTGenericReferences : UnityEngine.MonoBehaviour"); codes.Add("{"); + codes.Add(""); + codes.Add("\t// {{ constraint implement type"); + + codes.Add("\t// }} "); + + codes.Add(""); + codes.Add("\t// {{ AOT generic type"); foreach(var type in types) { - codes.Add($"\t//{type.Type}"); + codes.Add($"\t//{type.ToTypeSig()}"); } + codes.Add("\t// }}"); + + codes.Add(""); codes.Add("\tpublic void RefMethods()"); codes.Add("\t{"); foreach(var method in methods) { - codes.Add($"\t\t// {method.Method}"); + codes.Add($"\t\t// {method.ToMethodSpec()}"); } codes.Add("\t}"); diff --git a/Editor/EqualityUtil.cs b/Editor/EqualityUtil.cs index a50226b..b4223a4 100644 --- a/Editor/EqualityUtil.cs +++ b/Editor/EqualityUtil.cs @@ -9,6 +9,19 @@ namespace HybridCLR.Editor { public static class EqualityUtil { + public static bool EqualsTypeSig(TypeSig a, TypeSig b) + { + if (a == b) + { + return true; + } + if (a != null && b != null) + { + return TypeEqualityComparer.Instance.Equals(a, b); + } + return false; + } + public static bool EqualsTypeSigArray(List a, List b) { if (a == b) diff --git a/Editor/Meta/GenericClass.cs b/Editor/Meta/GenericClass.cs index c913fd1..d10c16e 100644 --- a/Editor/Meta/GenericClass.cs +++ b/Editor/Meta/GenericClass.cs @@ -48,6 +48,11 @@ namespace HybridCLR.Editor.Meta return hash; } + public TypeSig ToTypeSig() + { + return new GenericInstSig(this.Type.ToTypeSig().ToClassOrValueTypeSig(), this.KlassInst); + } + public static GenericClass ResolveClass(TypeSpec type, GenericArgumentContext ctx) { var sig = type.TypeSig.ToGenericInstSig(); diff --git a/Editor/Meta/GenericMethod.cs b/Editor/Meta/GenericMethod.cs index cdbcfdc..9989209 100644 --- a/Editor/Meta/GenericMethod.cs +++ b/Editor/Meta/GenericMethod.cs @@ -55,6 +55,14 @@ namespace HybridCLR.Editor.Meta return hash; } + public MethodSpec ToMethodSpec() + { + IMethodDefOrRef mt = KlassInst != null ? + (IMethodDefOrRef)new MemberRefUser(this.Method.Module, Method.Name, Method.MethodSig, new TypeSpecUser(new GenericInstSig(this.Method.DeclaringType.ToTypeSig().ToClassOrValueTypeSig(), this.KlassInst))) + : this.Method; + return new MethodSpecUser(mt, new GenericInstMethodSig(MethodInst)); + } + public static GenericMethod ResolveMethod(IMethod method, GenericArgumentContext ctx) { //Debug.Log($"== resolve method:{method}");