diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrGenerator.cs b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrGenerator.cs
index 215d93c9de6..55e8cdaed3f 100644
--- a/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrGenerator.cs
+++ b/src/Xamarin.Android.Build.Tasks/Utilities/LlvmIrGenerator/LlvmIrGenerator.cs
@@ -93,6 +93,24 @@ public LlvmTypeInfo (bool isPointer, bool isAggregate, bool isStructure, ulong s
}
}
+ ///
+ /// Everything
+ /// needs in order to emit a basic scalar type. Both members depend only on the managed type and
+ /// on , which is fixed for the lifetime of a generator instance, so they can
+ /// be computed once per type instead of once per written value.
+ ///
+ sealed class BasicTypeWriteInfo
+ {
+ public readonly string IRType;
+ public readonly LlvmTypeInfo TypeInfo;
+
+ public BasicTypeWriteInfo (string irType, LlvmTypeInfo typeInfo)
+ {
+ IRType = irType;
+ TypeInfo = typeInfo;
+ }
+ }
+
sealed class BasicType
{
public readonly string Name;
@@ -162,6 +180,7 @@ public BasicType (string name, ulong size, bool isNumeric = true, bool isUnsigne
public bool EmitComments { get; set; }
LlvmIrModuleTarget target;
+ readonly Dictionary basicTypeWriteCache = new Dictionary ();
protected LlvmIrGenerator (string filePath, LlvmIrModuleTarget target)
{
@@ -492,6 +511,14 @@ void WriteType (GeneratorWriteContext context, Type type, object? value, out Llv
// an array or a string blob, so skip the reflection-heavy probing below. Arrays and string
// blobs write one element at a time, so this runs millions of times for a typical
// application and `Type.IsPrimitive`/`Type.IsArray` dominate the generator otherwise.
+ // The IR type name and the `LlvmTypeInfo` are the same for every value of a given type,
+ // so they are computed once and memoized - a single dictionary lookup per written value.
+ if (basicTypeWriteCache.TryGetValue (type, out BasicTypeWriteInfo cachedBasicType)) {
+ typeInfo = cachedBasicType.TypeInfo;
+ context.Output.Write (cachedBasicType.IRType);
+ return;
+ }
+
if (basicTypeMap.ContainsKey (type)) {
string basicIRType = GetIRType (context, type, out ulong basicSize, out bool basicIsPointer);
typeInfo = new LlvmTypeInfo (
@@ -501,6 +528,7 @@ void WriteType (GeneratorWriteContext context, Type type, object? value, out Llv
size: basicSize,
maxFieldAlignment: basicSize
);
+ basicTypeWriteCache.Add (type, new BasicTypeWriteInfo (basicIRType, typeInfo));
context.Output.Write (basicIRType);
return;
}