Skip to content

Commit

Permalink
Avoid generating duplicated symbols when patch method (#1174)
Browse files Browse the repository at this point in the history
* Avoid generating duplicated symbols when patch method

* Use TryGetValue
  • Loading branch information
hez2010 authored Apr 22, 2022
1 parent 0df367b commit 6728f2c
Showing 1 changed file with 30 additions and 22 deletions.
52 changes: 30 additions & 22 deletions src/Perf/IIDOptimizer/GuidPatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ class GuidPatcher
private readonly Dictionary<TypeReference, MethodDefinition> ClosedTypeGuidDataMapping = new Dictionary<TypeReference, MethodDefinition>();
private readonly TypeDefinition guidImplementationDetailsType;
private readonly TypeDefinition guidDataBlockType;
private SignatureGenerator signatureGenerator;

private readonly SignatureGenerator signatureGenerator;
private readonly Dictionary<string, MethodReference> methodCache;

public GuidPatcher(AssemblyDefinition winRTRuntime, AssemblyDefinition targetAssembly)
{
assembly = targetAssembly;
Expand Down Expand Up @@ -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();
}

Expand All @@ -101,6 +102,7 @@ public GuidPatcher(AssemblyDefinition winRTRuntime, AssemblyDefinition targetAss
}

signatureGenerator = new SignatureGenerator(assembly, guidAttributeType!, winRTRuntimeAssembly);
methodCache = new Dictionary<string, MethodReference>();
}

public int ProcessAssembly()
Expand Down Expand Up @@ -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 = $"<IIDData>{type.FullName}";

var guidDataMethod = new MethodDefinition($"<IIDData>{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);
Expand All @@ -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)",
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -367,6 +375,6 @@ private int ProcessMethodBody(MethodBody body, MethodDefinition getTypeFromHandl
}
}
return numberOfReplacements;
}
}
}
}
}

0 comments on commit 6728f2c

Please sign in to comment.