From b4b070468f3e379016dfe22969c6682b62baa904 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 17 Jul 2022 08:37:38 +0200 Subject: [PATCH] Revert "Performance Optimization: Do no longer collect all lower case type and member names." This reverts commit 6584a2f5763256e2298dd9b5d859d7bb95ac4193. --- .../CSharp/Transforms/DeclareVariables.cs | 4 +- .../IL/Transforms/AssignVariableNames.cs | 82 +++++++++++++++---- 2 files changed, 65 insertions(+), 21 deletions(-) diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs index 8d414f2db..4eda0ba10 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs @@ -203,7 +203,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms #region EnsureExpressionStatementsAreValid void EnsureExpressionStatementsAreValid(AstNode rootNode) { - string[] reservedNames = null; foreach (var stmt in rootNode.DescendantsAndSelf.OfType()) { if (!IsValidInStatementExpression(stmt.Expression)) @@ -219,7 +218,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } else { - reservedNames ??= rootNode.DescendantsAndSelf.OfType().Select(i => i.Name).ToArray(); // assign result to dummy variable var type = stmt.Expression.GetResolveResult().Type; var v = function.RegisterVariable( @@ -228,7 +226,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms AssignVariableNames.GenerateVariableName(function, type, stmt.Expression.Annotations.OfType() .Where(AssignVariableNames.IsSupportedInstruction).FirstOrDefault(), - reservedNames: reservedNames) + mustResolveConflicts: true) ); stmt.Expression = new AssignmentExpression( new IdentifierExpression(v.Name).WithRR(new ILVariableResolveResult(v, v.Type)), diff --git a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs index a440725eb..da8730287 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs @@ -53,6 +53,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms }; ILTransformContext context; + List currentLowerCaseTypeOrMemberNames; Dictionary reservedVariableNames; Dictionary localFunctionMapping; HashSet loopCounters; @@ -63,6 +64,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms this.context = context; reservedVariableNames = new Dictionary(); + currentLowerCaseTypeOrMemberNames = new List(); + 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(); loopCounters = CollectLoopCounters(function); foreach (var f in function.Descendants.OfType()) @@ -146,6 +157,24 @@ namespace ICSharpCode.Decompiler.IL.Transforms } } + static IEnumerable CollectAllLowerCaseMemberNames(ITypeDefinition type) + { + foreach (var item in type.GetMembers(m => IsLowerCase(m.Name))) + yield return item.Name; + } + + static IEnumerable 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) { return name.Length > 0 && char.ToLower(name[0]) == name[0]; @@ -396,7 +425,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms var proposedNameForAddress = variable.AddressInstructions.OfType() .Select(arg => arg.Parent is CallInstruction c ? c.GetParameter(arg.ChildIndex)?.Name : null) .Where(arg => !string.IsNullOrWhiteSpace(arg)) - .ToList(); + .Except(currentLowerCaseTypeOrMemberNames).ToList(); if (proposedNameForAddress.Count > 0) { proposedName = proposedNameForAddress[0]; @@ -406,7 +435,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms { var proposedNameForStores = variable.StoreInstructions.OfType() .Select(expr => GetNameFromInstruction(expr.Value)) - .ToList(); + .Except(currentLowerCaseTypeOrMemberNames).ToList(); if (proposedNameForStores.Count == 1) { proposedName = proposedNameForStores[0]; @@ -416,7 +445,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms { var proposedNameForLoads = variable.LoadInstructions .Select(arg => GetNameForArgument(arg.Parent, arg.ChildIndex)) - .ToList(); + .Except(currentLowerCaseTypeOrMemberNames).ToList(); if (proposedNameForLoads.Count == 1) { proposedName = proposedNameForLoads[0]; @@ -426,7 +455,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms { var proposedNameForStoresFromNewObj = variable.StoreInstructions.OfType() .Select(expr => GetNameByType(GuessType(variable.Type, expr.Value, context))) - .ToList(); + .Except(currentLowerCaseTypeOrMemberNames).ToList(); if (proposedNameForStoresFromNewObj.Count == 1) { proposedName = proposedNameForStoresFromNewObj[0]; @@ -660,8 +689,35 @@ namespace ICSharpCode.Decompiler.IL.Transforms return variableType; } + static Dictionary CollectReservedVariableNames(ILFunction function, + ILVariable existingVariable, bool mustResolveConflicts) + { + var reservedVariableNames = new Dictionary(); + var rootFunction = function.Ancestors.OfType().Single(f => f.Parent == null); + foreach (var f in rootFunction.Descendants.OfType()) + { + 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, - ILVariable existingVariable = null, string[] reservedNames = null) + ILVariable existingVariable = null, bool mustResolveConflicts = false) { if (function == null) throw new ArgumentNullException(nameof(function)); @@ -669,12 +725,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms { return existingVariable.Name; } - - var reservedVariableNames = new Dictionary(); - foreach (var name in reservedNames ?? Array.Empty()) - { - reservedVariableNames[name] = 1; - } + var reservedVariableNames = CollectReservedVariableNames(function, existingVariable, mustResolveConflicts); string baseName = GetNameFromInstruction(valueContext); if (string.IsNullOrEmpty(baseName)) @@ -726,16 +777,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms internal static string GenerateVariableName(ILFunction function, IType type, ILInstruction valueContext = null, ILVariable existingVariable = null, - string[] reservedNames = null) + bool mustResolveConflicts = false) { if (function == null) throw new ArgumentNullException(nameof(function)); - - var reservedVariableNames = new Dictionary(); - foreach (var name in reservedNames ?? Array.Empty()) - { - reservedVariableNames[name] = 1; - } + var reservedVariableNames = CollectReservedVariableNames(function, existingVariable, mustResolveConflicts); string baseName = valueContext != null ? GetNameFromInstruction(valueContext) ?? GetNameByType(type) : GetNameByType(type); string proposedName = "obj";