Browse Source

Performance Optimization: Do no longer collect all lower case type and member names.

pull/2752/head
Siegfried Pammer 3 years ago
parent
commit
6584a2f576
  1. 4
      ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs
  2. 82
      ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

4
ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs

@ -203,6 +203,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
#region EnsureExpressionStatementsAreValid #region EnsureExpressionStatementsAreValid
void EnsureExpressionStatementsAreValid(AstNode rootNode) void EnsureExpressionStatementsAreValid(AstNode rootNode)
{ {
string[] reservedNames = null;
foreach (var stmt in rootNode.DescendantsAndSelf.OfType<ExpressionStatement>()) foreach (var stmt in rootNode.DescendantsAndSelf.OfType<ExpressionStatement>())
{ {
if (!IsValidInStatementExpression(stmt.Expression)) if (!IsValidInStatementExpression(stmt.Expression))
@ -218,6 +219,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
} }
else else
{ {
reservedNames ??= rootNode.DescendantsAndSelf.OfType<Identifier>().Select(i => i.Name).ToArray();
// assign result to dummy variable // assign result to dummy variable
var type = stmt.Expression.GetResolveResult().Type; var type = stmt.Expression.GetResolveResult().Type;
var v = function.RegisterVariable( var v = function.RegisterVariable(
@ -226,7 +228,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
AssignVariableNames.GenerateVariableName(function, type, AssignVariableNames.GenerateVariableName(function, type,
stmt.Expression.Annotations.OfType<ILInstruction>() stmt.Expression.Annotations.OfType<ILInstruction>()
.Where(AssignVariableNames.IsSupportedInstruction).FirstOrDefault(), .Where(AssignVariableNames.IsSupportedInstruction).FirstOrDefault(),
mustResolveConflicts: true) reservedNames: reservedNames)
); );
stmt.Expression = new AssignmentExpression( stmt.Expression = new AssignmentExpression(
new IdentifierExpression(v.Name).WithRR(new ILVariableResolveResult(v, v.Type)), new IdentifierExpression(v.Name).WithRR(new ILVariableResolveResult(v, v.Type)),

82
ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

@ -53,7 +53,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
}; };
ILTransformContext context; ILTransformContext context;
List<string> currentLowerCaseTypeOrMemberNames;
Dictionary<string, int> reservedVariableNames; Dictionary<string, int> reservedVariableNames;
Dictionary<MethodDefinitionHandle, string> localFunctionMapping; Dictionary<MethodDefinitionHandle, string> localFunctionMapping;
HashSet<ILVariable> loopCounters; HashSet<ILVariable> loopCounters;
@ -64,16 +63,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
this.context = context; this.context = context;
reservedVariableNames = new Dictionary<string, int>(); reservedVariableNames = new Dictionary<string, int>();
currentLowerCaseTypeOrMemberNames = new List<string>();
var currentLowerCaseMemberNames = CollectAllLowerCaseMemberNames(function.Method.DeclaringTypeDefinition);
foreach (var name in currentLowerCaseMemberNames)
currentLowerCaseTypeOrMemberNames.Add(name);
var currentLowerCaseTypeNames = CollectAllLowerCaseTypeNames(function.Method.DeclaringTypeDefinition);
foreach (var name in currentLowerCaseTypeNames)
{
currentLowerCaseTypeOrMemberNames.Add(name);
AddExistingName(reservedVariableNames, name);
}
localFunctionMapping = new Dictionary<MethodDefinitionHandle, string>(); localFunctionMapping = new Dictionary<MethodDefinitionHandle, string>();
loopCounters = CollectLoopCounters(function); loopCounters = CollectLoopCounters(function);
foreach (var f in function.Descendants.OfType<ILFunction>()) foreach (var f in function.Descendants.OfType<ILFunction>())
@ -157,24 +146,6 @@ namespace ICSharpCode.Decompiler.IL.Transforms
} }
} }
static IEnumerable<string> CollectAllLowerCaseMemberNames(ITypeDefinition type)
{
foreach (var item in type.GetMembers(m => IsLowerCase(m.Name)))
yield return item.Name;
}
static IEnumerable<string> CollectAllLowerCaseTypeNames(ITypeDefinition type)
{
foreach (var item in type.ParentModule.TopLevelTypeDefinitions)
{
if (item.Namespace != type.Namespace)
continue;
if (IsLowerCase(item.Name))
yield return item.Name;
}
}
static bool IsLowerCase(string name) static bool IsLowerCase(string name)
{ {
return name.Length > 0 && char.ToLower(name[0]) == name[0]; return name.Length > 0 && char.ToLower(name[0]) == name[0];
@ -425,7 +396,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var proposedNameForAddress = variable.AddressInstructions.OfType<LdLoca>() var proposedNameForAddress = variable.AddressInstructions.OfType<LdLoca>()
.Select(arg => arg.Parent is CallInstruction c ? c.GetParameter(arg.ChildIndex)?.Name : null) .Select(arg => arg.Parent is CallInstruction c ? c.GetParameter(arg.ChildIndex)?.Name : null)
.Where(arg => !string.IsNullOrWhiteSpace(arg)) .Where(arg => !string.IsNullOrWhiteSpace(arg))
.Except(currentLowerCaseTypeOrMemberNames).ToList(); .ToList();
if (proposedNameForAddress.Count > 0) if (proposedNameForAddress.Count > 0)
{ {
proposedName = proposedNameForAddress[0]; proposedName = proposedNameForAddress[0];
@ -435,7 +406,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{ {
var proposedNameForStores = variable.StoreInstructions.OfType<StLoc>() var proposedNameForStores = variable.StoreInstructions.OfType<StLoc>()
.Select(expr => GetNameFromInstruction(expr.Value)) .Select(expr => GetNameFromInstruction(expr.Value))
.Except(currentLowerCaseTypeOrMemberNames).ToList(); .ToList();
if (proposedNameForStores.Count == 1) if (proposedNameForStores.Count == 1)
{ {
proposedName = proposedNameForStores[0]; proposedName = proposedNameForStores[0];
@ -445,7 +416,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{ {
var proposedNameForLoads = variable.LoadInstructions var proposedNameForLoads = variable.LoadInstructions
.Select(arg => GetNameForArgument(arg.Parent, arg.ChildIndex)) .Select(arg => GetNameForArgument(arg.Parent, arg.ChildIndex))
.Except(currentLowerCaseTypeOrMemberNames).ToList(); .ToList();
if (proposedNameForLoads.Count == 1) if (proposedNameForLoads.Count == 1)
{ {
proposedName = proposedNameForLoads[0]; proposedName = proposedNameForLoads[0];
@ -455,7 +426,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{ {
var proposedNameForStoresFromNewObj = variable.StoreInstructions.OfType<StLoc>() var proposedNameForStoresFromNewObj = variable.StoreInstructions.OfType<StLoc>()
.Select(expr => GetNameByType(GuessType(variable.Type, expr.Value, context))) .Select(expr => GetNameByType(GuessType(variable.Type, expr.Value, context)))
.Except(currentLowerCaseTypeOrMemberNames).ToList(); .ToList();
if (proposedNameForStoresFromNewObj.Count == 1) if (proposedNameForStoresFromNewObj.Count == 1)
{ {
proposedName = proposedNameForStoresFromNewObj[0]; proposedName = proposedNameForStoresFromNewObj[0];
@ -689,35 +660,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return variableType; return variableType;
} }
static Dictionary<string, int> CollectReservedVariableNames(ILFunction function,
ILVariable existingVariable, bool mustResolveConflicts)
{
var reservedVariableNames = new Dictionary<string, int>();
var rootFunction = function.Ancestors.OfType<ILFunction>().Single(f => f.Parent == null);
foreach (var f in rootFunction.Descendants.OfType<ILFunction>())
{
foreach (var p in rootFunction.Parameters)
{
AddExistingName(reservedVariableNames, p.Name);
}
foreach (var v in f.Variables.Where(v => v.Kind != VariableKind.Parameter))
{
if (v != existingVariable)
AddExistingName(reservedVariableNames, v.Name);
}
}
if (mustResolveConflicts)
{
var memberNames = CollectAllLowerCaseMemberNames(function.Method.DeclaringTypeDefinition)
.Concat(CollectAllLowerCaseTypeNames(function.Method.DeclaringTypeDefinition));
foreach (var name in memberNames)
AddExistingName(reservedVariableNames, name);
}
return reservedVariableNames;
}
internal static string GenerateForeachVariableName(ILFunction function, ILInstruction valueContext, internal static string GenerateForeachVariableName(ILFunction function, ILInstruction valueContext,
ILVariable existingVariable = null, bool mustResolveConflicts = false) ILVariable existingVariable = null, string[] reservedNames = null)
{ {
if (function == null) if (function == null)
throw new ArgumentNullException(nameof(function)); throw new ArgumentNullException(nameof(function));
@ -725,7 +669,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{ {
return existingVariable.Name; return existingVariable.Name;
} }
var reservedVariableNames = CollectReservedVariableNames(function, existingVariable, mustResolveConflicts);
var reservedVariableNames = new Dictionary<string, int>();
foreach (var name in reservedNames ?? Array.Empty<string>())
{
reservedVariableNames[name] = 1;
}
string baseName = GetNameFromInstruction(valueContext); string baseName = GetNameFromInstruction(valueContext);
if (string.IsNullOrEmpty(baseName)) if (string.IsNullOrEmpty(baseName))
@ -777,11 +726,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms
internal static string GenerateVariableName(ILFunction function, IType type, internal static string GenerateVariableName(ILFunction function, IType type,
ILInstruction valueContext = null, ILVariable existingVariable = null, ILInstruction valueContext = null, ILVariable existingVariable = null,
bool mustResolveConflicts = false) string[] reservedNames = null)
{ {
if (function == null) if (function == null)
throw new ArgumentNullException(nameof(function)); throw new ArgumentNullException(nameof(function));
var reservedVariableNames = CollectReservedVariableNames(function, existingVariable, mustResolveConflicts);
var reservedVariableNames = new Dictionary<string, int>();
foreach (var name in reservedNames ?? Array.Empty<string>())
{
reservedVariableNames[name] = 1;
}
string baseName = valueContext != null ? GetNameFromInstruction(valueContext) ?? GetNameByType(type) : GetNameByType(type); string baseName = valueContext != null ? GetNameFromInstruction(valueContext) ?? GetNameByType(type) : GetNameByType(type);
string proposedName = "obj"; string proposedName = "obj";

Loading…
Cancel
Save