Browse Source

Reduced allocations

pull/1087/head
Pent Ploompuu 7 years ago
parent
commit
48dc32163e
  1. 17
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs
  2. 26
      ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterTokenWriter.cs
  3. 10
      ICSharpCode.Decompiler/CSharp/Syntax/CSharpModifierToken.cs
  4. 1
      ICSharpCode.Decompiler/IL/ILReader.cs
  5. 11
      ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs
  6. 5
      ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs
  7. 14
      ICSharpCode.Decompiler/Util/CollectionExtensions.cs

17
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs

@ -386,20 +386,25 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -386,20 +386,25 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
"from", "where", "join", "on", "equals", "into", "let", "orderby",
"ascending", "descending", "select", "group", "by"
};
static readonly int maxKeywordLength = unconditionalKeywords.Concat(queryKeywords).Max(s => s.Length);
/// <summary>
/// Determines whether the specified identifier is a keyword in the given context.
/// </summary>
public static bool IsKeyword(string identifier, AstNode context)
{
// only 2-10 char lower-case identifiers can be keywords
if (identifier.Length > maxKeywordLength || identifier.Length < 2 || identifier[0] < 'a') {
return false;
}
if (unconditionalKeywords.Contains(identifier)) {
return true;
}
foreach (AstNode ancestor in context.Ancestors) {
if (ancestor is QueryExpression && queryKeywords.Contains(identifier)) {
return true;
}
if (identifier == "await") {
if (queryKeywords.Contains(identifier)) {
return context.Ancestors.Any(ancestor => ancestor is QueryExpression);
}
if (identifier == "await") {
foreach (AstNode ancestor in context.Ancestors) {
// with lambdas/anonymous methods,
if (ancestor is LambdaExpression) {
return ((LambdaExpression)ancestor).IsAsync;

26
ICSharpCode.Decompiler/CSharp/OutputVisitor/TextWriterTokenWriter.cs

@ -239,13 +239,17 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -239,13 +239,17 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
}
if (value is string) {
string tmp = "\"" + ConvertString(value.ToString()) + "\"";
column += tmp.Length;
string tmp = ConvertString(value.ToString());
column += tmp.Length + 2;
textWriter.Write('"');
textWriter.Write(tmp);
textWriter.Write('"');
} else if (value is char) {
string tmp = "'" + ConvertCharLiteral((char)value) + "'";
column += tmp.Length;
string tmp = ConvertCharLiteral((char)value);
column += tmp.Length + 2;
textWriter.Write('\'');
textWriter.Write(tmp);
textWriter.Write('\'');
} else if (value is decimal) {
string str = ((decimal)value).ToString(NumberFormatInfo.InvariantInfo) + "m";
column += str.Length;
@ -342,7 +346,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -342,7 +346,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
if (ch == '\'') {
return "\\'";
}
return ConvertChar(ch);
return ConvertChar(ch) ?? ch.ToString();
}
/// <summary>
@ -376,7 +380,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -376,7 +380,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
case '^':
// ASCII characters we allow directly in the output even though we don't use
// other Unicode characters of the same category.
return ch.ToString();
return null;
default:
switch (char.GetUnicodeCategory(ch)) {
case UnicodeCategory.ModifierLetter:
@ -395,7 +399,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -395,7 +399,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
case UnicodeCategory.SpaceSeparator:
return "\\u" + ((int)ch).ToString("x4");
default:
return ch.ToString();
return null;
}
}
}
@ -407,11 +411,9 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -407,11 +411,9 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
StringBuilder sb = new StringBuilder ();
foreach (char ch in str) {
if (ch == '"') {
sb.Append("\\\"");
} else {
sb.Append(ConvertChar(ch));
}
string s = ch == '"' ? "\\\"" : ConvertChar(ch);
if (s != null) sb.Append(s);
else sb.Append(ch);
}
return sb.ToString();
}

10
ICSharpCode.Decompiler/CSharp/Syntax/CSharpModifierToken.cs

@ -25,7 +25,7 @@ @@ -25,7 +25,7 @@
// THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using ICSharpCode.Decompiler.CSharp.OutputVisitor;
namespace ICSharpCode.Decompiler.CSharp.Syntax
@ -61,7 +61,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -61,7 +61,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
// Not worth using a dictionary for such few elements.
// This table is sorted in the order that modifiers should be output when generating code.
static readonly Modifiers[] allModifiers = {
public static ImmutableArray<Modifiers> AllModifiers { get; } = ImmutableArray.Create(
Modifiers.Public, Modifiers.Private, Modifiers.Protected, Modifiers.Internal,
Modifiers.New,
Modifiers.Unsafe,
@ -71,11 +71,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -71,11 +71,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
Modifiers.Extern, Modifiers.Partial, Modifiers.Const,
Modifiers.Async,
Modifiers.Any
};
public static IEnumerable<Modifiers> AllModifiers {
get { return allModifiers; }
}
);
public CSharpModifierToken (TextLocation location, Modifiers modifier) : base (location, null)
{

1
ICSharpCode.Decompiler/IL/ILReader.cs

@ -996,7 +996,6 @@ namespace ICSharpCode.Decompiler.IL @@ -996,7 +996,6 @@ namespace ICSharpCode.Decompiler.IL
Debug.Assert(inst.ResultType != StackType.Void);
IType type = compilation.FindType(inst.ResultType.ToKnownTypeCode());
var v = new ILVariable(VariableKind.StackSlot, type, inst.ResultType, inst.ILRange.Start);
v.Name = "S_" + inst.ILRange.Start.ToString("x4");
v.HasGeneratedName = true;
currentStack = currentStack.Push(v);
return new StLoc(v, inst);

11
ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs

@ -40,10 +40,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -40,10 +40,10 @@ namespace ICSharpCode.Decompiler.IL.Transforms
static bool MightBeExpressionTree(ILInstruction inst, ILInstruction stmt)
{
if (!(inst is CallInstruction call
&& call.Method.FullName == "System.Linq.Expressions.Expression.Lambda"
&& call.Method.FullNameIs("System.Linq.Expressions.Expression", "Lambda")
&& call.Arguments.Count == 2))
return false;
if (call.Parent is CallInstruction parentCall && parentCall.Method.FullName == "System.Linq.Expressions.Expression.Quote")
if (call.Parent is CallInstruction parentCall && parentCall.Method.FullNameIs("System.Linq.Expressions.Expression", "Quote"))
return false;
if (!(IsEmptyParameterList(call.Arguments[1]) || (call.Arguments[1] is Block block && block.Kind == BlockKind.ArrayInitializer)))
return false;
@ -54,7 +54,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -54,7 +54,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
static bool IsEmptyParameterList(ILInstruction inst)
{
if (inst is CallInstruction emptyCall && emptyCall.Method.FullName == "System.Array.Empty" && emptyCall.Arguments.Count == 0)
if (inst is CallInstruction emptyCall && emptyCall.Method.FullNameIs("System.Array", "Empty") && emptyCall.Arguments.Count == 0)
return true;
if (inst.MatchNewArr(out var type) && type.FullName == "System.Linq.Expressions.ParameterExpression")
return true;
@ -78,13 +78,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -78,13 +78,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (!(init is CallInstruction initCall && initCall.Arguments.Count == 2))
return false;
IMethod parameterMethod = initCall.Method;
if (!(parameterMethod.Name == "Parameter" && parameterMethod.DeclaringType.FullName == "System.Linq.Expressions.Expression"))
if (!(initCall.Method.FullNameIs("System.Linq.Expressions.Expression", "Parameter")))
return false;
CallInstruction typeArg = initCall.Arguments[0] as CallInstruction;
if (typeArg == null || typeArg.Arguments.Count != 1)
return false;
if (typeArg.Method.FullName != "System.Type.GetTypeFromHandle")
if (!typeArg.Method.FullNameIs("System.Type", "GetTypeFromHandle"))
return false;
return typeArg.Arguments[0].MatchLdTypeToken(out type) && initCall.Arguments[1].MatchLdStr(out name);
}

5
ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs

@ -814,5 +814,10 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -814,5 +814,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
isGeneric = null;
return SpecialType.UnknownType;
}
public static bool FullNameIs(this IMethod method, string type, string name)
{
return method.Name == name && method.DeclaringType?.FullName == type;
}
}
}

14
ICSharpCode.Decompiler/Util/CollectionExtensions.cs

@ -252,5 +252,19 @@ namespace ICSharpCode.Decompiler.Util @@ -252,5 +252,19 @@ namespace ICSharpCode.Decompiler.Util
throw new ArgumentNullException(nameof(list));
list.RemoveAt(list.Count - 1);
}
#region Aliases/shortcuts for Enumerable extension methods
public static bool Any<T>(this ICollection<T> list) => list.Count > 0;
public static bool Any<T>(this T[] array, Predicate<T> match) => Array.Exists(array, match);
public static bool Any<T>(this List<T> list, Predicate<T> match) => list.Exists(match);
public static bool All<T>(this T[] array, Predicate<T> match) => Array.TrueForAll(array, match);
public static bool All<T>(this List<T> list, Predicate<T> match) => list.TrueForAll(match);
public static T FirstOrDefault<T>(this T[] array, Predicate<T> predicate) => Array.Find(array, predicate);
public static T FirstOrDefault<T>(this List<T> list, Predicate<T> predicate) => list.Find(predicate);
public static T Last<T>(this IList<T> list) => list[list.Count - 1];
#endregion
}
}

Loading…
Cancel
Save