Browse Source

CachedDelegateInitialization: extend Roslyn pattern for non-static context

pull/734/merge
Siegfried Pammer 8 years ago
parent
commit
bd1e164fdc
  1. 36
      ICSharpCode.Decompiler/IL/Transforms/CachedDelegateInitialization.cs

36
ICSharpCode.Decompiler/IL/Transforms/CachedDelegateInitialization.cs

@ -41,7 +41,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -41,7 +41,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
ILInlining.InlineIfPossible(block, ref i, context);
continue;
}
if (CachedDelegateInitializationRoslynWithLocal(inst)) {
if (CachedDelegateInitializationRoslynInStaticWithLocal(inst) || CachedDelegateInitializationRoslynWithLocal(inst)) {
block.Instructions.RemoveAt(i);
continue;
}
@ -123,7 +123,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -123,7 +123,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
/// =>
/// stloc s(DelegateConstruction)
/// </summary>
bool CachedDelegateInitializationRoslynWithLocal(IfInstruction inst)
bool CachedDelegateInitializationRoslynInStaticWithLocal(IfInstruction inst)
{
Block trueInst = inst.TrueInst as Block;
if (trueInst == null || (trueInst.Instructions.Count != 1) || !inst.FalseInst.MatchNop())
@ -142,6 +142,38 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -142,6 +142,38 @@ namespace ICSharpCode.Decompiler.IL.Transforms
return false;
if (!DelegateConstruction.IsDelegateConstruction((NewObj)stobj.Value, true))
return false;
context.Step("CachedDelegateInitializationRoslynInStaticWithLocal", inst);
storeBeforeIf.Value = stobj.Value;
return true;
}
/// <summary>
/// stloc s(ldobj(ldflda(CachedAnonMethodDelegate))
/// if (comp(ldloc s == null)) {
/// stloc s(stobj(ldflda(CachedAnonMethodDelegate), DelegateConstruction))
/// }
/// =>
/// stloc s(DelegateConstruction)
/// </summary>
bool CachedDelegateInitializationRoslynWithLocal(IfInstruction inst)
{
Block trueInst = inst.TrueInst as Block;
if (trueInst == null || (trueInst.Instructions.Count != 1) || !inst.FalseInst.MatchNop())
return false;
if (!inst.Condition.MatchCompEquals(out ILInstruction left, out ILInstruction right) || !left.MatchLdLoc(out ILVariable s) || !right.MatchLdNull())
return false;
var storeInst = trueInst.Instructions.Last() as StLoc;
var storeBeforeIf = inst.Parent.Children.ElementAtOrDefault(inst.ChildIndex - 1) as StLoc;
if (storeBeforeIf == null || storeInst == null || storeBeforeIf.Variable != s || storeInst.Variable != s)
return false;
if (!(storeInst.Value is StObj stobj) || !(storeBeforeIf.Value is LdObj ldobj))
return false;
if (!(stobj.Value is NewObj))
return false;
if (!stobj.Target.MatchLdFlda(out var _, out var field1) || !ldobj.Target.MatchLdFlda(out var __, out var field2) || !field1.Equals(field2))
return false;
if (!DelegateConstruction.IsDelegateConstruction((NewObj)stobj.Value, true))
return false;
context.Step("CachedDelegateInitializationRoslynWithLocal", inst);
storeBeforeIf.Value = stobj.Value;
return true;

Loading…
Cancel
Save