Browse Source

Avoid reference count temporarily dropping to zero while ConditionDetection moves instructions to other blocks.

This avoids recursively un-registering e.g. all LdLocs from their ILVariable.LoadInstructions, etc. (all the ILInstruction.Disconnected logic). This speeds up the example from #1193 by another factor 2.
pull/3111/head
Daniel Grunwald 2 years ago
parent
commit
5a5be026d0
  1. 17
      ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs
  2. 5
      ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs

17
ICSharpCode.Decompiler/IL/ControlFlow/ConditionDetection.cs

@ -230,7 +230,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -230,7 +230,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
{
context.Step("Embed else-block for goto removal", ifInst);
Debug.Assert(IsEmpty(ifInst.FalseInst));
ifInst.FalseInst = ExtractBlock(block, block.Instructions.IndexOf(ifInst) + 1, block.Instructions.Count - 1);
Block newBlock = new Block();
ifInst.FalseInst = newBlock;
ExtractBlock(block, block.Instructions.IndexOf(ifInst) + 1, block.Instructions.Count - 1, newBlock);
}
// if (...) { ...; goto blockExit; } blockExit;
@ -375,6 +377,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -375,6 +377,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
//save a copy
var thenInst = ifInst.TrueInst;
thenInst.AddRef();
if (ifInst != block.Instructions.SecondToLastOrDefault())
{
@ -382,12 +385,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -382,12 +385,14 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// Note that this will only extract instructions that were previously inlined from another block
// (via InlineExitBranch), so the instructions are already fully-transformed.
// So it's OK to move them into a nested block again (which hides them from the following block transforms).
ifInst.TrueInst = ExtractBlock(block, block.Instructions.IndexOf(ifInst) + 1, block.Instructions.Count);
var newBlock = new Block();
ifInst.TrueInst = newBlock;
ExtractBlock(block, block.Instructions.IndexOf(ifInst) + 1, block.Instructions.Count, newBlock);
}
else
{
block.Instructions.RemoveAt(block.Instructions.Count - 1);
ifInst.TrueInst = exitInst;
block.Instructions.RemoveAt(block.Instructions.Count - 1);
}
if (thenInst is Block thenBlock)
@ -398,6 +403,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -398,6 +403,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
{
block.Instructions.Add(thenInst);
}
thenInst.ReleaseRef();
ifInst.Condition = Comp.LogicNot(ifInst.Condition);
ExpressionTransforms.RunOnSingleStatement(ifInst, context);
@ -662,9 +668,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -662,9 +668,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
/// <summary>
/// Removes a subrange of instructions from a block and returns them in a new Block
/// </summary>
internal static Block ExtractBlock(Block block, int startIndex, int endIndex)
internal static void ExtractBlock(Block block, int startIndex, int endIndex, Block extractedBlock)
{
var extractedBlock = new Block();
for (int i = startIndex; i < endIndex; i++)
{
var inst = block.Instructions[i];
@ -672,8 +677,6 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -672,8 +677,6 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
extractedBlock.AddILRange(inst);
}
block.Instructions.RemoveRange(startIndex, endIndex - startIndex);
return extractedBlock;
}
}
}

5
ICSharpCode.Decompiler/IL/Transforms/HighLevelLoopTransform.cs

@ -92,8 +92,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -92,8 +92,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
ifInstruction.Condition = Comp.LogicNot(ifInstruction.Condition);
ifInstruction.FalseInst = ifInstruction.TrueInst;
//move the rest of the body into a new block
loopBody = ConditionDetection.ExtractBlock(loop.EntryPoint, 1, loop.EntryPoint.Instructions.Count);
loopBody = new Block();
loopBody.AddRef();
ConditionDetection.ExtractBlock(loop.EntryPoint, 1, loop.EntryPoint.Instructions.Count, loopBody);
loop.Blocks.Insert(1, loopBody);
loopBody.ReleaseRef();
if (!loopBody.HasFlag(InstructionFlags.EndPointUnreachable))
loopBody.Instructions.Add(new Leave(loop));

Loading…
Cancel
Save