Files

154 lines
4.6 KiB
C#
Raw Normal View History

2026-08-27 10:56:38 -06:00
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.PooledObjects;
namespace Microsoft.CodeAnalysis.CSharp.CodeGen;
internal class Optimizer
{
public static BoundStatement Optimize(BoundStatement src, bool debugFriendly, out HashSet<LocalSymbol> stackLocals)
{
PooledDictionary<LocalSymbol, LocalDefUseInfo> instance = PooledDictionary<LocalSymbol, LocalDefUseInfo>.GetInstance();
src = (BoundStatement)StackOptimizerPass1.Analyze(src, (Dictionary<LocalSymbol, LocalDefUseInfo>)(object)instance, debugFriendly);
FilterValidStackLocals((Dictionary<LocalSymbol, LocalDefUseInfo>)(object)instance);
BoundStatement result;
if (((Dictionary<LocalSymbol, LocalDefUseInfo>)(object)instance).Count == 0)
{
stackLocals = null;
result = src;
}
else
{
stackLocals = new HashSet<LocalSymbol>(((Dictionary<LocalSymbol, LocalDefUseInfo>)(object)instance).Keys);
result = StackOptimizerPass2.Rewrite(src, (Dictionary<LocalSymbol, LocalDefUseInfo>)(object)instance);
}
foreach (LocalDefUseInfo value in ((Dictionary<LocalSymbol, LocalDefUseInfo>)(object)instance).Values)
{
value.Free();
}
instance.Free();
return result;
}
private static void FilterValidStackLocals(Dictionary<LocalSymbol, LocalDefUseInfo> info)
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: Invalid comparison between Unknown and I4
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
ArrayBuilder<LocalDefUseInfo> instance = ArrayBuilder<LocalDefUseInfo>.GetInstance();
LocalSymbol[] array = info.Keys.ToArray();
foreach (LocalSymbol localSymbol in array)
{
LocalDefUseInfo localDefUseInfo = info[localSymbol];
if ((int)localSymbol.SynthesizedKind == -3)
{
instance.Add(localDefUseInfo);
info.Remove(localSymbol);
}
else if (localDefUseInfo.CannotSchedule)
{
localDefUseInfo.Free();
info.Remove(localSymbol);
}
}
if (info.Count != 0)
{
RemoveIntersectingLocals(info, instance);
}
Enumerator<LocalDefUseInfo> enumerator = instance.GetEnumerator();
while (enumerator.MoveNext())
{
enumerator.Current.Free();
}
instance.Free();
}
private static void RemoveIntersectingLocals(Dictionary<LocalSymbol, LocalDefUseInfo> info, ArrayBuilder<LocalDefUseInfo> dummies)
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
ArrayBuilder<LocalDefUseSpan> instance = ArrayBuilder<LocalDefUseSpan>.GetInstance(dummies.Count);
Enumerator<LocalDefUseInfo> enumerator = dummies.GetEnumerator();
while (enumerator.MoveNext())
{
Enumerator<LocalDefUseSpan> enumerator2 = enumerator.Current.LocalDefs.GetEnumerator();
while (enumerator2.MoveNext())
{
LocalDefUseSpan current = enumerator2.Current;
if (current.Start != current.End)
{
instance.Add(current);
}
}
}
int count = instance.Count;
foreach (var item in from _003C_003Eh__TransparentIdentifier0 in info.SelectMany(delegate(KeyValuePair<LocalSymbol, LocalDefUseInfo> i)
{
KeyValuePair<LocalSymbol, LocalDefUseInfo> keyValuePair = i;
return (IEnumerable<LocalDefUseSpan>)keyValuePair.Value.LocalDefs;
}, (KeyValuePair<LocalSymbol, LocalDefUseInfo> i, LocalDefUseSpan d2) => new
{
i = i,
d = d2
})
orderby _003C_003Eh__TransparentIdentifier0.d.End - _003C_003Eh__TransparentIdentifier0.d.Start, _003C_003Eh__TransparentIdentifier0.d.End
select new
{
i = _003C_003Eh__TransparentIdentifier0.i.Key,
d = _003C_003Eh__TransparentIdentifier0.d
})
{
if (!info.ContainsKey(item.i))
{
continue;
}
LocalDefUseSpan d = item.d;
int count2 = instance.Count;
bool flag;
if (count2 > 5000)
{
flag = true;
}
else
{
flag = false;
for (int num = 0; num < count; num++)
{
LocalDefUseSpan dummy = instance[num];
if (d.ConflictsWithDummy(dummy))
{
flag = true;
break;
}
}
if (!flag)
{
for (int num2 = count; num2 < count2; num2++)
{
LocalDefUseSpan other = instance[num2];
if (d.ConflictsWith(other))
{
flag = true;
break;
}
}
}
}
if (flag)
{
info[item.i].LocalDefs.Free();
info.Remove(item.i);
}
else
{
instance.Add(d);
}
}
instance.Free();
}
}