Browse Source

Optimize ProxyCallReplacer: ignore calls to static methods as those can never be a call to a proxy.

Enable FixProxyCalls test for rosyln+opt
pull/1464/head
Siegfried Pammer 6 years ago
parent
commit
1c261c6170
  1. 2
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  2. 4
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/FixProxyCalls.cs
  3. 37
      ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs

2
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -252,7 +252,7 @@ namespace ICSharpCode.Decompiler.Tests
} }
[Test] [Test]
public void FixProxyCalls([Values(CompilerOptions.None, CompilerOptions.Optimize, CompilerOptions.UseRoslyn)] CompilerOptions cscOptions) public void FixProxyCalls([ValueSource(nameof(defaultOptions))] CompilerOptions cscOptions)
{ {
RunForLibrary(cscOptions: cscOptions); RunForLibrary(cscOptions: cscOptions);
} }

4
ICSharpCode.Decompiler.Tests/TestCases/Pretty/FixProxyCalls.cs

@ -92,9 +92,11 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.ILPretty
internal class H : G internal class H : G
{ {
private Action<string> action;
protected internal override void Test(string test) protected internal override void Test(string test)
{ {
Action<string> action = delegate(string a) { action = delegate(string a) {
base.Test(a); base.Test(a);
}; };
if (test.Equals(1)) { if (test.Equals(1)) {

37
ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs

@ -17,6 +17,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
void Run(CallInstruction inst, ILTransformContext context) void Run(CallInstruction inst, ILTransformContext context)
{ {
if (inst.Method.IsStatic)
return;
if (inst.Method.MetadataToken.IsNil || inst.Method.MetadataToken.Kind != HandleKind.MethodDefinition) if (inst.Method.MetadataToken.IsNil || inst.Method.MetadataToken.Kind != HandleKind.MethodDefinition)
return; return;
var handle = (MethodDefinitionHandle)inst.Method.MetadataToken; var handle = (MethodDefinitionHandle)inst.Method.MetadataToken;
@ -42,28 +44,33 @@ namespace ICSharpCode.Decompiler.IL.Transforms
if (blockContainer.Blocks.Count != 1) if (blockContainer.Blocks.Count != 1)
return; return;
var block = blockContainer.Blocks[0]; var block = blockContainer.Blocks[0];
Call call = null; Call call;
if (block.Instructions.Count == 1) { ILInstruction returnValue;
// leave IL_0000 (call Test(ldloc this, ldloc A_1)) switch (block.Instructions.Count) {
if (!block.Instructions[0].MatchLeave(blockContainer, out ILInstruction returnValue)) case 1:
return; // leave IL_0000 (call Test(ldloc this, ldloc A_1))
call = returnValue as Call; if (!block.Instructions[0].MatchLeave(blockContainer, out returnValue))
} else if (block.Instructions.Count == 2) { return;
// call Test(ldloc this, ldloc A_1) call = returnValue as Call;
// leave IL_0000(nop) break;
call = block.Instructions[0] as Call; case 2:
if (!block.Instructions[1].MatchLeave(blockContainer, out ILInstruction returnValue)) // call Test(ldloc this, ldloc A_1)
return; // leave IL_0000(nop)
if (!returnValue.MatchNop()) call = block.Instructions[0] as Call;
if (!block.Instructions[1].MatchLeave(blockContainer, out returnValue))
return;
if (!returnValue.MatchNop())
return;
break;
default:
return; return;
} }
if (call == null || call.Method.IsConstructor) { if (call == null || call.Method.IsConstructor) {
return; return;
} }
if (call.Method.IsStatic != inst.Method.IsStatic || call.Method.Parameters.Count != inst.Method.Parameters.Count) { if (call.Method.IsStatic || call.Method.Parameters.Count != inst.Method.Parameters.Count) {
return; return;
} }
// check if original arguments are only correct ldloc calls // check if original arguments are only correct ldloc calls
for (int i = 0; i < call.Arguments.Count; i++) { for (int i = 0; i < call.Arguments.Count; i++) {
var originalArg = call.Arguments[i]; var originalArg = call.Arguments[i];

Loading…
Cancel
Save