From aca7dd0a6726b26f49550a685dcff7a2a7bd8988 Mon Sep 17 00:00:00 2001 From: walon Date: Thu, 30 May 2024 12:11:05 +0800 Subject: [PATCH] =?UTF-8?q?[new]=20=E6=96=B0=E5=A2=9EGeneratedAOTGenericRe?= =?UTF-8?q?ferenceExcludeExistsAOTClassAndMethods=EF=BC=8C=E8=AE=A1?= =?UTF-8?q?=E7=AE=97=E7=83=AD=E6=9B=B4=E6=96=B0=E5=BC=95=E7=94=A8=E7=9A=84?= =?UTF-8?q?AOT=E6=B3=9B=E5=9E=8B=E7=B1=BB=E5=9E=8B=E5=92=8C=E5=87=BD?= =?UTF-8?q?=E6=95=B0=E6=97=B6=E6=8E=92=E9=99=A4=E6=8E=89AOT=E4=B8=AD?= =?UTF-8?q?=E5=B7=B2=E7=BB=8F=E5=AD=98=E5=9C=A8=E7=9A=84=E6=B3=9B=E5=9E=8B?= =?UTF-8?q?=E5=92=8C=E5=87=BD=E6=95=B0=EF=BC=8C=E6=9C=80=E7=BB=88=E7=94=9F?= =?UTF-8?q?=E6=88=90=E6=9B=B4=E7=B2=BE=E5=87=86=E7=9A=84=E8=A1=A5=E5=85=85?= =?UTF-8?q?=E5=85=83=E6=95=B0=E6=8D=AE=E7=A8=8B=E5=BA=8F=E9=9B=86=E5=88=97?= =?UTF-8?q?=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Editor/AOT/Analyzer.cs | 7 +- .../Commands/AOTReferenceGeneratorCommand.cs | 88 +++++++++++++++++++ 2 files changed, 94 insertions(+), 1 deletion(-) diff --git a/Editor/AOT/Analyzer.cs b/Editor/AOT/Analyzer.cs index 68253e3..dcd2a87 100644 --- a/Editor/AOT/Analyzer.cs +++ b/Editor/AOT/Analyzer.cs @@ -17,12 +17,16 @@ namespace HybridCLR.Editor.AOT public AssemblyReferenceDeepCollector Collector { get; set; } public int MaxIterationCount { get; set; } + + public bool ComputeAotAssembly { get; set; } } private readonly int _maxInterationCount; private readonly AssemblyReferenceDeepCollector _assemblyCollector; + private readonly bool _computeAotAssembly; + private readonly HashSet _genericTypes = new HashSet(); private readonly HashSet _genericMethods = new HashSet(); @@ -47,6 +51,7 @@ namespace HybridCLR.Editor.AOT { _assemblyCollector = options.Collector; _maxInterationCount = options.MaxIterationCount; + _computeAotAssembly = options.ComputeAotAssembly; _methodReferenceAnalyzer = new MethodReferenceAnalyzer(this.OnNewMethod); _hotUpdateAssemblyFiles = new HashSet(options.Collector.GetRootAssemblyNames().Select(assName => assName + ".dll")); } @@ -71,7 +76,7 @@ namespace HybridCLR.Editor.AOT private bool IsAotType(TypeDef type) { - return !_hotUpdateAssemblyFiles.Contains(type.Module.Name); + return _computeAotAssembly || !_hotUpdateAssemblyFiles.Contains(type.Module.Name); } private bool IsAotGenericMethod(MethodDef method) diff --git a/Editor/Commands/AOTReferenceGeneratorCommand.cs b/Editor/Commands/AOTReferenceGeneratorCommand.cs index c2d6340..b4dfb41 100644 --- a/Editor/Commands/AOTReferenceGeneratorCommand.cs +++ b/Editor/Commands/AOTReferenceGeneratorCommand.cs @@ -2,6 +2,7 @@ using HybridCLR.Editor.Meta; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -22,6 +23,10 @@ namespace HybridCLR.Editor.Commands GenerateAOTGenericReference(target); } + /// + /// 计算热更代码中的泛型引用 + /// + /// public static void GenerateAOTGenericReference(BuildTarget target) { var gs = SettingsUtil.HybridCLRSettings; @@ -40,5 +45,88 @@ namespace HybridCLR.Editor.Commands writer.Write(analyzer.AotGenericTypes.ToList(), analyzer.AotGenericMethods.ToList(), $"{Application.dataPath}/{gs.outputAOTGenericReferenceFile}"); AssetDatabase.Refresh(); } + + + + //[MenuItem("HybridCLR/Generate/AOTGenericReference2", priority = 103)] + //public static void GeneratedAOTGenericReferenceExcludeExists() + //{ + // GeneratedAOTGenericReferenceExcludeExists(EditorUserBuildSettings.activeBuildTarget); + //} + + /// + /// 计算热更新代码中的泛型引用,但排除AOT已经存在的泛型引用 + /// + /// + /// + public static void GeneratedAOTGenericReferenceExcludeExistsAOTClassAndMethods(BuildTarget target) + { + + var gs = SettingsUtil.HybridCLRSettings; + List hotUpdateDllNames = SettingsUtil.HotUpdateAssemblyNamesExcludePreserved; + + AssemblyReferenceDeepCollector hotUpdateCollector = new AssemblyReferenceDeepCollector(MetaUtil.CreateHotUpdateAndAOTAssemblyResolver(target, hotUpdateDllNames), hotUpdateDllNames); + var hotUpdateAnalyzer = new Analyzer(new Analyzer.Options + { + MaxIterationCount = Math.Min(10, gs.maxGenericReferenceIteration), + Collector = hotUpdateCollector, + }); + + hotUpdateAnalyzer.Run(); + + + string aotDllDir = SettingsUtil.GetAssembliesPostIl2CppStripDir(target); + List aotAssemblyNames = Directory.Exists(aotDllDir) ? + Directory.GetFiles(aotDllDir, "*.dll", SearchOption.TopDirectoryOnly).Select(Path.GetFileNameWithoutExtension).ToList() + : new List(); + if (aotAssemblyNames.Count == 0) + { + throw new Exception($"no aot assembly found. please run `HybridCLR/Generate/All` or `HybridCLR/Generate/AotDlls` to generate aot dlls before runing `HybridCLR/Generate/AOTGenericReference`"); + } + AssemblyReferenceDeepCollector aotCollector = new AssemblyReferenceDeepCollector(MetaUtil.CreateAOTAssemblyResolver(target), aotAssemblyNames); + var aotAnalyzer = new Analyzer(new Analyzer.Options + { + MaxIterationCount = Math.Min(10, gs.maxGenericReferenceIteration), + Collector = aotCollector, + ComputeAotAssembly = true, + }); + + aotAnalyzer.Run(); + + var (resultTypes, resultMethods) = ExcludeExistAOTGenericTypeAndMethodss(hotUpdateAnalyzer.AotGenericTypes.ToList(), hotUpdateAnalyzer.AotGenericMethods.ToList(), aotAnalyzer.AotGenericTypes.ToList(), aotAnalyzer.AotGenericMethods.ToList()); + var writer = new GenericReferenceWriter(); + writer.Write(resultTypes, resultMethods, $"{Application.dataPath}/{gs.outputAOTGenericReferenceFile}"); + AssetDatabase.Refresh(); + } + + + private static (List, List) ExcludeExistAOTGenericTypeAndMethodss(List hotUpdateTypes, List hotUpdateMethods, List aotTypes, List aotMethods) + { + var types = new List(); + + var typeSig2Type = hotUpdateTypes.ToDictionary(t => t.Type.DefinitionAssembly.Name + ":" + t.ToTypeSig(), t => t); + foreach (var t in aotTypes) + { + string key = t.Type.DefinitionAssembly.Name + ":" + t.ToTypeSig(); + if (typeSig2Type.TryGetValue(key, out var removedType)) + { + typeSig2Type.Remove(key); + Debug.Log($"remove AOT type:{removedType.ToTypeSig()} "); + } + } + + var methodSig2Method = hotUpdateMethods.ToDictionary(m => m.Method.DeclaringType.DefinitionAssembly.Name + ":" + m.ToMethodSpec().ToString(), m => m); + foreach (var m in aotMethods) + { + string key = m.Method.DeclaringType.DefinitionAssembly.Name + ":" + m.ToMethodSpec().ToString(); + if (methodSig2Method.TryGetValue(key, out var removedMethod)) + { + methodSig2Method.Remove(key); + Debug.Log($"remove AOT method:{removedMethod.ToMethodSpec()} "); + } + } + + return (typeSig2Type.Values.ToList(), methodSig2Method.Values.ToList()); + } } }