Browse Source

Check the CancellationToken a bit more frequently.

pull/734/merge
Daniel Grunwald 8 years ago
parent
commit
2207ab40f7
  1. 9
      ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs
  2. 19
      ICSharpCode.Decompiler/FlowAnalysis/ReachingDefinitionsVisitor.cs
  3. 2
      ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs
  4. 2
      ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs
  5. 4
      ICSharpCode.Decompiler/IL/ControlFlow/ExitPoints.cs
  6. 3
      ICSharpCode.Decompiler/IL/ControlFlow/StateRangeAnalysis.cs
  7. 1
      ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs
  8. 3
      ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs
  9. 6
      ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs
  10. 2
      ICSharpCode.Decompiler/IL/Transforms/RemoveDeadVariableInit.cs
  11. 5
      ICSharpCode.Decompiler/IL/Transforms/SplitVariables.cs

9
ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System.Diagnostics;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Util;
using System.Threading;
namespace ICSharpCode.Decompiler.FlowAnalysis
{
@ -100,12 +101,15 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -100,12 +101,15 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
return bits[variableIndex];
}
}
readonly CancellationToken cancellationToken;
readonly ILFunction scope;
readonly BitSet variablesWithUninitializedUsage;
public DefiniteAssignmentVisitor(ILFunction scope)
public DefiniteAssignmentVisitor(ILFunction scope, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
this.cancellationToken = cancellationToken;
this.scope = scope;
this.variablesWithUninitializedUsage = new BitSet(scope.Variables.Count);
base.flagsRequiringManualImpl |= InstructionFlags.MayReadLocals | InstructionFlags.MayWriteLocals;
@ -120,6 +124,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -120,6 +124,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
void HandleStore(ILVariable v)
{
cancellationToken.ThrowIfCancellationRequested();
if (v.Function == scope) {
// Mark the variable as initialized:
state.MarkVariableInitialized(v.IndexInFunction);

19
ICSharpCode.Decompiler/FlowAnalysis/ReachingDefinitionsVisitor.cs

@ -22,6 +22,7 @@ using System.Diagnostics; @@ -22,6 +22,7 @@ using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Util;
using System.Threading;
namespace ICSharpCode.Decompiler.FlowAnalysis
{
@ -188,8 +189,10 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -188,8 +189,10 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
/// </summary>
const int FirstStoreIndex = 1;
#endregion
#region Documentation + member fields
protected readonly CancellationToken cancellationToken;
/// <summary>
/// The function being analyzed.
/// </summary>
@ -234,9 +237,10 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -234,9 +237,10 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
/// The analysis will track all variables in the scope for which the predicate returns true
/// ("analyzed variables").
/// </summary>
public ReachingDefinitionsVisitor(ILFunction scope, Predicate<ILVariable> pred)
: this(scope, GetActiveVariableBitSet(scope, pred))
public ReachingDefinitionsVisitor(ILFunction scope, Predicate<ILVariable> pred, CancellationToken cancellationToken)
: this(scope, GetActiveVariableBitSet(scope, pred), cancellationToken)
{
this.cancellationToken = cancellationToken;
}
static BitSet GetActiveVariableBitSet(ILFunction scope, Predicate<ILVariable> pred)
@ -255,7 +259,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -255,7 +259,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
///
/// The analysis will track all variables in the scope for which <c>analyzedVariables[v.IndexInScope]</c> is true.
/// </summary>
public ReachingDefinitionsVisitor(ILFunction scope, BitSet analyzedVariables)
public ReachingDefinitionsVisitor(ILFunction scope, BitSet analyzedVariables, CancellationToken cancellationToken)
{
if (scope == null)
throw new ArgumentNullException(nameof(scope));
@ -266,11 +270,12 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -266,11 +270,12 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
base.flagsRequiringManualImpl |= InstructionFlags.MayWriteLocals;
// Fill `allStores` and `storeIndexMap` and `firstStoreIndexForVariable`.
var storesByVar = FindAllStoresByVariable(scope, analyzedVariables);
var storesByVar = FindAllStoresByVariable(scope, analyzedVariables, cancellationToken);
allStores = new ILInstruction[FirstStoreIndex + storesByVar.Sum(l => l != null ? l.Count : 0)];
firstStoreIndexForVariable = new int[scope.Variables.Count + 1];
int si = FirstStoreIndex;
for (int vi = 0; vi < storesByVar.Length; vi++) {
cancellationToken.ThrowIfCancellationRequested();
firstStoreIndexForVariable[vi] = si;
var stores = storesByVar[vi];
if (stores != null) {
@ -300,7 +305,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -300,7 +305,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
/// <summary>
/// Fill <c>allStores</c> and <c>storeIndexMap</c>.
/// </summary>
static List<ILInstruction>[] FindAllStoresByVariable(ILFunction scope, BitSet activeVariables)
static List<ILInstruction>[] FindAllStoresByVariable(ILFunction scope, BitSet activeVariables, CancellationToken cancellationToken)
{
// For each variable, find the list of ILInstructions storing to that variable
List<ILInstruction>[] storesByVar = new List<ILInstruction>[scope.Variables.Count];
@ -310,6 +315,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -310,6 +315,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
}
foreach (var inst in scope.Descendants) {
if (inst.HasDirectFlag(InstructionFlags.MayWriteLocals)) {
cancellationToken.ThrowIfCancellationRequested();
ILVariable v = ((IInstructionWithVariableOperand)inst).Variable;
if (v.Function == scope && activeVariables[v.IndexInFunction]) {
storesByVar[v.IndexInFunction].Add(inst);
@ -339,6 +345,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -339,6 +345,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
#region Analysis
void HandleStore(ILInstruction inst, ILVariable v)
{
cancellationToken.ThrowIfCancellationRequested();
if (v.Function == scope && analyzedVariables[v.IndexInFunction] && state.IsReachable) {
// Clear the set of stores for this variable:
state.KillStores(firstStoreIndexForVariable[v.IndexInFunction], firstStoreIndexForVariable[v.IndexInFunction + 1]);

2
ICSharpCode.Decompiler/IL/ControlFlow/ControlFlowSimplification.cs

@ -39,6 +39,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -39,6 +39,8 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
public void Run(ILFunction function, ILTransformContext context)
{
foreach (var block in function.Descendants.OfType<Block>()) {
context.CancellationToken.ThrowIfCancellationRequested();
// Remove 'nop' instructions
block.Instructions.RemoveAll(inst => inst.OpCode == OpCode.Nop);

2
ICSharpCode.Decompiler/IL/ControlFlow/DetectPinnedRegions.cs

@ -56,6 +56,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -56,6 +56,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
public void Run(ILFunction function, ILTransformContext context)
{
foreach (var container in function.Descendants.OfType<BlockContainer>()) {
context.CancellationToken.ThrowIfCancellationRequested();
SplitBlocksAtWritesToPinnedLocals(container);
DetectNullSafeArrayToPointer(container);
foreach (var block in container.Blocks)
@ -64,6 +65,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -64,6 +65,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
}
// Sometimes there's leftover writes to the original pinned locals
foreach (var block in function.Descendants.OfType<Block>()) {
context.CancellationToken.ThrowIfCancellationRequested();
for (int i = 0; i < block.Instructions.Count; i++) {
var stloc = block.Instructions[i] as StLoc;
if (stloc != null && stloc.Variable.Kind == VariableKind.PinnedLocal && stloc.Variable.LoadCount == 0 && stloc.Variable.AddressCount == 0) {

4
ICSharpCode.Decompiler/IL/ControlFlow/ExitPoints.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Diagnostics;
using ICSharpCode.Decompiler.IL.Transforms;
using System.Threading;
namespace ICSharpCode.Decompiler.IL.ControlFlow
{
@ -100,6 +101,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -100,6 +101,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
}
}
CancellationToken cancellationToken;
BlockContainer currentContainer;
/// <summary>
@ -112,6 +114,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -112,6 +114,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
public void Run(ILFunction function, ILTransformContext context)
{
cancellationToken = context.CancellationToken;
currentExit = NoExit;
function.AcceptVisitor(this);
}
@ -149,6 +152,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -149,6 +152,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
protected internal override void VisitBlock(Block block)
{
cancellationToken.ThrowIfCancellationRequested();
// Don't use foreach loop, because the children might add to the block
for (int i = 0; i < block.Instructions.Count; i++) {
block.Instructions[i].AcceptVisitor(this);

3
ICSharpCode.Decompiler/IL/ControlFlow/StateRangeAnalysis.cs

@ -23,6 +23,7 @@ using System.Collections.Generic; @@ -23,6 +23,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL.ControlFlow
@ -49,6 +50,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -49,6 +50,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
/// </remarks>
class StateRangeAnalysis
{
public CancellationToken CancellationToken;
readonly StateRangeAnalysisMode mode;
readonly IField stateField;
readonly SymbolicEvaluationContext evalContext;
@ -80,6 +82,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -80,6 +82,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
/// </returns>
public LongSet AssignStateRanges(ILInstruction inst, LongSet stateRange)
{
CancellationToken.ThrowIfCancellationRequested();
switch (inst) {
case BlockContainer blockContainer:
AddStateRange(blockContainer.EntryPoint, stateRange);

1
ICSharpCode.Decompiler/IL/ControlFlow/SwitchDetection.cs

@ -41,6 +41,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -41,6 +41,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
foreach (var container in function.Descendants.OfType<BlockContainer>()) {
bool blockContainerNeedsCleanup = false;
foreach (var block in container.Blocks) {
context.CancellationToken.ThrowIfCancellationRequested();
ProcessBlock(block, ref blockContainerNeedsCleanup);
}
if (blockContainerNeedsCleanup) {

3
ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs

@ -443,6 +443,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -443,6 +443,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
// So for reconstructing the control flow, we only consider the blocks directly within body.
var rangeAnalysis = new StateRangeAnalysis(StateRangeAnalysisMode.IteratorMoveNext, stateField);
rangeAnalysis.CancellationToken = context.CancellationToken;
rangeAnalysis.AssignStateRanges(body, LongSet.Universe);
var newBody = ConvertBody(body, rangeAnalysis.GetBlockStateSetMapping(body));
@ -517,6 +518,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -517,6 +518,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
var oldBlock = oldBody.Blocks[i];
var newBlock = newBody.Blocks[i];
foreach (var oldInst in oldBlock.Instructions) {
context.CancellationToken.ThrowIfCancellationRequested();
if (oldInst.MatchStFld(out var target, out var field, out var value) && target.MatchLdThis()) {
if (field.MemberDefinition.Equals(stateField)) {
if (value.MatchLdcI4(out int newState)) {
@ -723,6 +725,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow @@ -723,6 +725,7 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
stateToContainer.Add(-1, newBody);
// First, analyse the newBody: for each block, determine the active state number.
foreach (var block in newBody.Blocks) {
context.CancellationToken.ThrowIfCancellationRequested();
int oldState = blockState[block.ChildIndex];
BlockContainer container; // new container for the block
if (GetNewState(block) is int newState) {

6
ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs

@ -39,6 +39,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -39,6 +39,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var targetsToReplace = new List<IInstructionWithVariableOperand>();
foreach (var block in function.Descendants.OfType<Block>()) {
for (int i = block.Instructions.Count - 1; i >= 0; i--) {
context.CancellationToken.ThrowIfCancellationRequested();
foreach (var call in block.Instructions[i].Descendants.OfType<NewObj>()) {
ILInstruction target;
ILFunction f = TransformDelegateConstruction(call, out target);
@ -67,9 +68,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -67,9 +68,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms
function.AcceptVisitor(new TransformDisplayClassUsages(target, target.Variable.CaptureScope, orphanedVariableInits));
}
foreach (var store in orphanedVariableInits) {
ILInstruction containingBlock = store.Parent as Block;
if (containingBlock != null)
((Block)containingBlock).Instructions.Remove(store);
if (store.Parent is Block containingBlock)
containingBlock.Instructions.Remove(store);
}
}

2
ICSharpCode.Decompiler/IL/Transforms/RemoveDeadVariableInit.cs

@ -30,7 +30,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -30,7 +30,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
public void Run(ILFunction function, ILTransformContext context)
{
var visitor = new DefiniteAssignmentVisitor(function);
var visitor = new DefiniteAssignmentVisitor(function, context.CancellationToken);
function.Body.AcceptVisitor(visitor);
foreach (var v in function.Variables) {
if (v.Kind != VariableKind.Parameter && !visitor.IsPotentiallyUsedUninitialized(v)) {

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

@ -20,6 +20,7 @@ using System.Collections.Generic; @@ -20,6 +20,7 @@ using System.Collections.Generic;
using System.Linq;
using ICSharpCode.Decompiler.FlowAnalysis;
using ICSharpCode.Decompiler.Util;
using System.Threading;
namespace ICSharpCode.Decompiler.IL.Transforms
{
@ -30,7 +31,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -30,7 +31,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
{
public void Run(ILFunction function, ILTransformContext context)
{
var groupStores = new GroupStores(function);
var groupStores = new GroupStores(function, context.CancellationToken);
function.Body.AcceptVisitor(groupStores);
var newVariables = new Dictionary<ILInstruction, ILVariable>();
// Replace analyzed variables with their split versions:
@ -67,7 +68,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms @@ -67,7 +68,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
readonly UnionFind<IInstructionWithVariableOperand> unionFind = new UnionFind<IInstructionWithVariableOperand>();
readonly HashSet<IInstructionWithVariableOperand> uninitVariableUsage = new HashSet<IInstructionWithVariableOperand>();
public GroupStores(ILFunction scope) : base(scope, IsCandidateVariable)
public GroupStores(ILFunction scope, CancellationToken cancellationToken) : base(scope, IsCandidateVariable, cancellationToken)
{
}

Loading…
Cancel
Save