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

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

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

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

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

Loading…
Cancel
Save