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

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

@ -92,8 +92,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
ifInstruction.Condition = Comp.LogicNot(ifInstruction.Condition); ifInstruction.Condition = Comp.LogicNot(ifInstruction.Condition);
ifInstruction.FalseInst = ifInstruction.TrueInst; ifInstruction.FalseInst = ifInstruction.TrueInst;
//move the rest of the body into a new block //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); loop.Blocks.Insert(1, loopBody);
loopBody.ReleaseRef();
if (!loopBody.HasFlag(InstructionFlags.EndPointUnreachable)) if (!loopBody.HasFlag(InstructionFlags.EndPointUnreachable))
loopBody.Instructions.Add(new Leave(loop)); loopBody.Instructions.Add(new Leave(loop));

Loading…
Cancel
Save