Browse Source

Improve cancellation.

pull/863/head
Daniel Grunwald 8 years ago
parent
commit
71defde402
  1. 14
      ICSharpCode.Decompiler/IL/BlockBuilder.cs
  2. 2
      ICSharpCode.Decompiler/IL/ILReader.cs
  3. 3
      ICSharpCode.Decompiler/IL/Transforms/LoopingTransform.cs
  4. 6
      ILSpy/Languages/ILAstLanguage.cs

14
ICSharpCode.Decompiler/IL/BlockBuilder.cs

@ -21,6 +21,7 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
@ -107,13 +108,14 @@ namespace ICSharpCode.Decompiler.IL
Block currentBlock; Block currentBlock;
Stack<BlockContainer> containerStack = new Stack<BlockContainer>(); Stack<BlockContainer> containerStack = new Stack<BlockContainer>();
public void CreateBlocks(BlockContainer mainContainer, List<ILInstruction> instructions, BitArray incomingBranches) public void CreateBlocks(BlockContainer mainContainer, List<ILInstruction> instructions, BitArray incomingBranches, CancellationToken cancellationToken)
{ {
CreateContainerStructure(); CreateContainerStructure();
mainContainer.ILRange = new Interval(0, body.CodeSize); mainContainer.ILRange = new Interval(0, body.CodeSize);
currentContainer = mainContainer; currentContainer = mainContainer;
foreach (var inst in instructions) { foreach (var inst in instructions) {
cancellationToken.ThrowIfCancellationRequested();
int start = inst.ILRange.Start; int start = inst.ILRange.Start;
if (currentBlock == null || incomingBranches[start]) { if (currentBlock == null || incomingBranches[start]) {
// Finish up the previous block // Finish up the previous block
@ -153,7 +155,7 @@ namespace ICSharpCode.Decompiler.IL
} }
FinalizeCurrentBlock(body.CodeSize, fallthrough: false); FinalizeCurrentBlock(body.CodeSize, fallthrough: false);
containerStack.Clear(); containerStack.Clear();
ConnectBranches(mainContainer); ConnectBranches(mainContainer, cancellationToken);
} }
private void FinalizeCurrentBlock(int currentILOffset, bool fallthrough) private void FinalizeCurrentBlock(int currentILOffset, bool fallthrough)
@ -166,10 +168,11 @@ namespace ICSharpCode.Decompiler.IL
currentBlock = null; currentBlock = null;
} }
void ConnectBranches(ILInstruction inst) void ConnectBranches(ILInstruction inst, CancellationToken cancellationToken)
{ {
switch (inst) { switch (inst) {
case Branch branch: case Branch branch:
cancellationToken.ThrowIfCancellationRequested();
Debug.Assert(branch.TargetBlock == null); Debug.Assert(branch.TargetBlock == null);
branch.TargetBlock = FindBranchTarget(branch.TargetILOffset); branch.TargetBlock = FindBranchTarget(branch.TargetILOffset);
break; break;
@ -184,7 +187,8 @@ namespace ICSharpCode.Decompiler.IL
case BlockContainer container: case BlockContainer container:
containerStack.Push(container); containerStack.Push(container);
foreach (var block in container.Blocks) { foreach (var block in container.Blocks) {
ConnectBranches(block); cancellationToken.ThrowIfCancellationRequested();
ConnectBranches(block, cancellationToken);
if (block.Instructions.Count == 0 || !block.Instructions.Last().HasFlag(InstructionFlags.EndPointUnreachable)) { if (block.Instructions.Count == 0 || !block.Instructions.Last().HasFlag(InstructionFlags.EndPointUnreachable)) {
block.Instructions.Add(new InvalidBranch("Unexpected end of block")); block.Instructions.Add(new InvalidBranch("Unexpected end of block"));
} }
@ -193,7 +197,7 @@ namespace ICSharpCode.Decompiler.IL
break; break;
default: default:
foreach (var child in inst.Children) foreach (var child in inst.Children)
ConnectBranches(child); ConnectBranches(child, cancellationToken);
break; break;
} }
} }

2
ICSharpCode.Decompiler/IL/ILReader.cs

@ -306,7 +306,7 @@ namespace ICSharpCode.Decompiler.IL
Init(body); Init(body);
ReadInstructions(cancellationToken); ReadInstructions(cancellationToken);
var blockBuilder = new BlockBuilder(body, typeSystem, variableByExceptionHandler); var blockBuilder = new BlockBuilder(body, typeSystem, variableByExceptionHandler);
blockBuilder.CreateBlocks(mainContainer, instructionBuilder, isBranchTarget); blockBuilder.CreateBlocks(mainContainer, instructionBuilder, isBranchTarget, cancellationToken);
var function = new ILFunction(body.Method, mainContainer); var function = new ILFunction(body.Method, mainContainer);
CollectionExtensions.AddRange(function.Variables, parameterVariables); CollectionExtensions.AddRange(function.Variables, parameterVariables);
CollectionExtensions.AddRange(function.Variables, localVariables); CollectionExtensions.AddRange(function.Variables, localVariables);

3
ICSharpCode.Decompiler/IL/Transforms/LoopingTransform.cs

@ -40,11 +40,12 @@ namespace ICSharpCode.Decompiler.IL.Transforms
throw new InvalidOperationException("LoopingBlockTransform already running. Transforms (and the CSharpDecompiler) are neither neither thread-safe nor re-entrant."); throw new InvalidOperationException("LoopingBlockTransform already running. Transforms (and the CSharpDecompiler) are neither neither thread-safe nor re-entrant.");
running = true; running = true;
try { try {
int count = 1;
do { do {
block.ResetDirty(); block.ResetDirty();
block.RunTransforms(children, context); block.RunTransforms(children, context);
if (block.IsDirty) if (block.IsDirty)
context.Step("Block is dirty; running another loop iteration.", block); context.Step($"Block is dirty; running loop iteration #{++count}.", block);
} while (block.IsDirty); } while (block.IsDirty);
} finally { } finally {
running = false; running = false;

6
ILSpy/Languages/ILAstLanguage.cs

@ -156,7 +156,11 @@ namespace ICSharpCode.ILSpy
ILReader reader = new ILReader(typeSystem); ILReader reader = new ILReader(typeSystem);
reader.UseDebugSymbols = options.DecompilerSettings.UseDebugSymbols; reader.UseDebugSymbols = options.DecompilerSettings.UseDebugSymbols;
ILFunction il = reader.ReadIL(method.Body, options.CancellationToken); ILFunction il = reader.ReadIL(method.Body, options.CancellationToken);
ILTransformContext context = new ILTransformContext { Settings = options.DecompilerSettings, TypeSystem = typeSystem }; ILTransformContext context = new ILTransformContext {
Settings = options.DecompilerSettings,
TypeSystem = typeSystem,
CancellationToken = options.CancellationToken
};
context.Stepper.StepLimit = options.StepLimit; context.Stepper.StepLimit = options.StepLimit;
context.Stepper.IsDebug = options.IsDebug; context.Stepper.IsDebug = options.IsDebug;
try { try {

Loading…
Cancel
Save