From 6728f2c3ac4e727b59234d00fe43d99a8da9096c Mon Sep 17 00:00:00 2001 From: Steve Date: Fri, 22 Apr 2022 10:24:20 +0800 Subject: [PATCH] Avoid generating duplicated symbols when patch method (#1174) * Avoid generating duplicated symbols when patch method * Use TryGetValue --- src/Perf/IIDOptimizer/GuidPatcher.cs | 52 ++++++++++++++++------------ 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/src/Perf/IIDOptimizer/GuidPatcher.cs b/src/Perf/IIDOptimizer/GuidPatcher.cs index 43f315e38..48d20b841 100644 --- a/src/Perf/IIDOptimizer/GuidPatcher.cs +++ b/src/Perf/IIDOptimizer/GuidPatcher.cs @@ -28,8 +28,9 @@ class GuidPatcher private readonly Dictionary ClosedTypeGuidDataMapping = new Dictionary(); private readonly TypeDefinition guidImplementationDetailsType; private readonly TypeDefinition guidDataBlockType; - private SignatureGenerator signatureGenerator; - + private readonly SignatureGenerator signatureGenerator; + private readonly Dictionary methodCache; + public GuidPatcher(AssemblyDefinition winRTRuntime, AssemblyDefinition targetAssembly) { assembly = targetAssembly; @@ -68,14 +69,14 @@ public GuidPatcher(AssemblyDefinition winRTRuntime, AssemblyDefinition targetAss getTypeFromHandleMethod = systemType.Methods.First(m => string.CompareOrdinal(m.Name, "GetTypeFromHandle") == 0); - guidGeneratorType = null; + guidGeneratorType = null; - TypeDefinition? typeExtensionsType = null; + TypeDefinition? typeExtensionsType = null; // Use the type definition if we are patching WinRT.Runtime, otherwise lookup the types as references if (string.CompareOrdinal(assembly.Name.Name, "WinRT.Runtime") == 0) { - guidGeneratorType = winRTRuntimeAssembly.MainModule.Types.Where(typeDef => string.CompareOrdinal(typeDef.Name, "GuidGenerator") == 0).First(); + guidGeneratorType = winRTRuntimeAssembly.MainModule.Types.Where(typeDef => string.CompareOrdinal(typeDef.Name, "GuidGenerator") == 0).First(); typeExtensionsType = winRTRuntimeAssembly.MainModule.Types.Where(typeDef => string.CompareOrdinal(typeDef.Name, "TypeExtensions") == 0).First(); } @@ -101,6 +102,7 @@ public GuidPatcher(AssemblyDefinition winRTRuntime, AssemblyDefinition targetAss } signatureGenerator = new SignatureGenerator(assembly, guidAttributeType!, winRTRuntimeAssembly); + methodCache = new Dictionary(); } public int ProcessAssembly() @@ -172,25 +174,31 @@ private bool PatchNonGenericTypeIID(MethodBody body, int startILIndex, TypeRefer private bool PatchGenericTypeIID(MethodBody body, int startILIndex, TypeReference type, int numberOfInstructionsToOverwrite) { SignaturePart rootSignaturePart = signatureGenerator.GetSignatureParts(type); + var methodName = $"{type.FullName}"; - var guidDataMethod = new MethodDefinition($"{type.FullName}", MethodAttributes.Assembly | MethodAttributes.Static, readOnlySpanOfByte); + if (!methodCache.TryGetValue(methodName, out var guidDataMethodReference)) + { + var guidDataMethod = new MethodDefinition(methodName, MethodAttributes.Assembly | MethodAttributes.Static, readOnlySpanOfByte); - guidImplementationDetailsType.Methods.Add(guidDataMethod); + guidImplementationDetailsType.Methods.Add(guidDataMethod); - var emitter = new SignatureEmitter(type, guidDataMethod); - VisitSignature(rootSignaturePart, emitter); - - emitter.EmitGuidGetter(guidDataBlockType, guidImplementationDetailsType, readOnlySpanOfByte, readOnlySpanOfByteCtor, guidGeneratorType!); + var emitter = new SignatureEmitter(type, guidDataMethod); + VisitSignature(rootSignaturePart, emitter); - MethodReference guidDataMethodReference = guidDataMethod; - if (guidDataMethodReference.HasGenericParameters) - { - var genericGuidDataMethodReference = new GenericInstanceMethod(guidDataMethodReference); - foreach (var param in guidDataMethodReference.GenericParameters) + emitter.EmitGuidGetter(guidDataBlockType, guidImplementationDetailsType, readOnlySpanOfByte, readOnlySpanOfByteCtor, guidGeneratorType!); + + guidDataMethodReference = guidDataMethod; + if (guidDataMethodReference.HasGenericParameters) { - genericGuidDataMethodReference.GenericArguments.Add(emitter.GenericParameterMapping[param]); + var genericGuidDataMethodReference = new GenericInstanceMethod(guidDataMethodReference); + foreach (var param in guidDataMethodReference.GenericParameters) + { + genericGuidDataMethodReference.GenericArguments.Add(emitter.GenericParameterMapping[param]); + } + guidDataMethodReference = genericGuidDataMethodReference; } - guidDataMethodReference = genericGuidDataMethodReference; + + methodCache[methodName] = guidDataMethodReference; } ReplaceWithCallToGuidDataGetter(body, startILIndex, numberOfInstructionsToOverwrite, guidDataMethodReference); @@ -214,7 +222,7 @@ private void VisitSignature(SignaturePart rootSignaturePart, SignatureEmitter em { case BasicSignaturePart basic: { - emitter.PushString(basic.Type switch + emitter.PushString(basic.Type switch { SignatureType.@string => "string", SignatureType.iinspectable => "cinterface(IInspectable)", @@ -258,7 +266,7 @@ private void VisitSignature(SignaturePart rootSignaturePart, SignatureEmitter em break; } } - + private int ProcessMethodBody(MethodBody body, MethodDefinition getTypeFromHandleMethod, MethodDefinition getIidMethod, MethodDefinition createIidMethod) { int numberOfReplacements = 0; @@ -367,6 +375,6 @@ private int ProcessMethodBody(MethodBody body, MethodDefinition getTypeFromHandl } } return numberOfReplacements; - } + } } -} +} \ No newline at end of file