Permalink
Browse files

Move decompilation to background thread.

  • Loading branch information...
1 parent d1c932b commit 158b10d2fb4e0ba11f5baf0407efda4491710361 @dgrunwald dgrunwald committed Feb 5, 2011
@@ -23,7 +23,7 @@
using System.Globalization;
using System.IO;
using System.Linq;
-
+using System.Threading;
using Mono.Cecil.Cil;
namespace ICSharpCode.Decompiler.FlowAnalysis
@@ -97,7 +97,7 @@ internal void ResetVisited()
}
}
- public void ComputeDominance()
+ public void ComputeDominance(CancellationToken cancellationToken = default(CancellationToken))
{
// A Simple, Fast Dominance Algorithm
// Keith D. Cooper, Timothy J. Harvey and Ken Kennedy
@@ -108,6 +108,8 @@ public void ComputeDominance()
changed = false;
ResetVisited();
+ cancellationToken.ThrowIfCancellationRequested();
+
// for all nodes b except the entry point
EntryPoint.TraversePreOrder(
b => b.Successors,
@@ -20,6 +20,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Threading;
using ICSharpCode.Decompiler.FlowAnalysis;
using Mono.Cecil.Cil;
@@ -30,11 +31,11 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
/// </summary>
public class ControlStructureDetector
{
- public static ControlStructure DetectStructure(ControlFlowGraph g, IEnumerable<ExceptionHandler> exceptionHandlers)
+ public static ControlStructure DetectStructure(ControlFlowGraph g, IEnumerable<ExceptionHandler> exceptionHandlers, CancellationToken cancellationToken)
{
ControlStructure root = new ControlStructure(new HashSet<ControlFlowNode>(g.Nodes), g.EntryPoint, ControlStructureType.Root);
DetectExceptionHandling(root, g, exceptionHandlers);
- DetectLoops(g, root);
+ DetectLoops(g, root, cancellationToken);
g.ResetVisited();
return root;
}
@@ -111,12 +112,13 @@ static void MoveControlStructures(ControlStructure current, ControlStructure tar
#endregion
#region Loop Detection
- static void DetectLoops(ControlFlowGraph g, ControlStructure current)
+ static void DetectLoops(ControlFlowGraph g, ControlStructure current, CancellationToken cancellationToken)
{
g.ResetVisited();
+ cancellationToken.ThrowIfCancellationRequested();
FindLoops(current, current.EntryPoint);
foreach (ControlStructure loop in current.Children)
- DetectLoops(g, loop);
+ DetectLoops(g, loop, cancellationToken);
}
static void FindLoops(ControlStructure current, ControlFlowNode node)
@@ -18,6 +18,7 @@
using System;
using System.IO;
+using System.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.FlowAnalysis;
using Mono.Cecil;
@@ -34,7 +35,7 @@ public class CSharpLanguage : Language
get { return "C#"; }
}
- public override void Decompile(MethodDefinition method, ITextOutput output)
+ public override void Decompile(MethodDefinition method, ITextOutput output, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
@@ -19,6 +19,8 @@
using System;
using System.ComponentModel;
using System.Linq;
+using System.Threading;
+
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.FlowAnalysis;
using Mono.Cecil;
@@ -36,10 +38,10 @@ public ILLanguage(bool detectControlStructure)
}
public override string Name {
- get { return detectControlStructure ? "IL (simplified)" : "IL"; }
+ get { return detectControlStructure ? "IL (structured)" : "IL"; }
}
- public override void Decompile(MethodDefinition method, ITextOutput output)
+ public override void Decompile(MethodDefinition method, ITextOutput output, CancellationToken cancellationToken)
{
output.WriteCommentLine("// Method begins at RVA 0x{0:x4}", method.RVA);
output.WriteCommentLine("// Code size {0} (0x{0:x})", method.Body.CodeSize);
@@ -66,9 +68,9 @@ public override void Decompile(MethodDefinition method, ITextOutput output)
if (detectControlStructure) {
var cfg = ControlFlowGraphBuilder.Build(method.Body);
- cfg.ComputeDominance();
+ cfg.ComputeDominance(cancellationToken);
cfg.ComputeDominanceFrontier();
- var s = ControlStructureDetector.DetectStructure(cfg, method.Body.ExceptionHandlers);
+ var s = ControlStructureDetector.DetectStructure(cfg, method.Body.ExceptionHandlers, cancellationToken);
WriteStructure(output, s);
} else {
foreach (var inst in method.Body.Instructions) {
@@ -20,6 +20,8 @@
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
+using System.Threading;
+
using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy
@@ -52,7 +54,7 @@ public virtual FilterResult Filter(FilterSettings settings)
return FilterResult.Hidden;
}
- public virtual void Decompile(Language language, ITextOutput output)
+ public virtual void Decompile(Language language, ITextOutput output, CancellationToken cancellationToken)
{
}
}
View
@@ -38,22 +38,11 @@ public interface ITextOutput
sealed class ReferenceSegment : TextSegment
{
public object Reference;
- public ILSpyTreeNode TreeNode;
}
- sealed class SmartTextOutput : ITextOutput
+ sealed class DefinitionLookup
{
- readonly StringBuilder b = new StringBuilder();
- int indent;
- bool needsIndent;
Dictionary<object, int> definitions = new Dictionary<object, int>();
- TextSegmentCollection<ReferenceSegment> references = new TextSegmentCollection<ReferenceSegment>();
-
- public TextSegmentCollection<ReferenceSegment> References {
- get { return references; }
- }
-
- public ILSpyTreeNode CurrentTreeNode;
public int GetDefinitionPosition(object definition)
{
@@ -64,6 +53,25 @@ public int GetDefinitionPosition(object definition)
return -1;
}
+ public void AddDefinition(object definition, int offset)
+ {
+ definitions[definition] = offset;
+ }
+ }
+
+ sealed class SmartTextOutput : ITextOutput
+ {
+ readonly StringBuilder b = new StringBuilder();
+ int indent;
+ bool needsIndent;
+ TextSegmentCollection<ReferenceSegment> references = new TextSegmentCollection<ReferenceSegment>();
+
+ public readonly DefinitionLookup DefinitionLookup = new DefinitionLookup();
+
+ public TextSegmentCollection<ReferenceSegment> References {
+ get { return references; }
+ }
+
public override string ToString()
{
return b.ToString();
@@ -118,7 +126,7 @@ public void WriteDefinition(string text, object definition)
{
WriteIndent();
b.Append(text);
- definitions[definition] = b.Length;
+ this.DefinitionLookup.AddDefinition(definition, b.Length);
}
public void WriteReference(string text, object reference)
@@ -127,7 +135,7 @@ public void WriteReference(string text, object reference)
int start = b.Length;
b.Append(text);
int end = b.Length;
- references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = reference, TreeNode = CurrentTreeNode });
+ references.Add(new ReferenceSegment { StartOffset = start, EndOffset = end, Reference = reference });
}
}
}
View
@@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
+using System.Threading;
using Mono.Cecil;
namespace ICSharpCode.ILSpy
@@ -34,23 +35,23 @@ public abstract class Language
get { return ICSharpCode.AvalonEdit.Highlighting.HighlightingManager.Instance.GetDefinition(this.Name); }
}
- public virtual void Decompile(MethodDefinition method, ITextOutput output)
+ public virtual void Decompile(MethodDefinition method, ITextOutput output, CancellationToken cancellationToken)
{
}
- public virtual void Decompile(PropertyDefinition property, ITextOutput output)
+ public virtual void Decompile(PropertyDefinition property, ITextOutput output, CancellationToken cancellationToken)
{
}
- public virtual void Decompile(FieldDefinition field, ITextOutput output)
+ public virtual void Decompile(FieldDefinition field, ITextOutput output, CancellationToken cancellationToken)
{
}
- public virtual void Decompile(EventDefinition ev, ITextOutput output)
+ public virtual void Decompile(EventDefinition ev, ITextOutput output, CancellationToken cancellationToken)
{
}
- public virtual void Decompile(TypeDefinition type, ITextOutput output)
+ public virtual void Decompile(TypeDefinition type, ITextOutput output, CancellationToken cancellationToken)
{
}
@@ -17,15 +17,19 @@
// DEALINGS IN THE SOFTWARE.
using System;
+using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.FlowAnalysis;
+using ICSharpCode.ILSpy.Disassembler;
using ICSharpCode.TreeView;
using Microsoft.Win32;
using Mono.Cecil;
@@ -210,31 +214,61 @@ void OpenFromGac_Click(object sender, RoutedEventArgs e)
}
}
- SmartTextOutput textOutput;
+ DefinitionLookup definitionLookup;
+ CancellationTokenSource currentCancellationTokenSource;
void TreeView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
- try {
- textEditor.SyntaxHighlighting = ILSpy.Language.Current.SyntaxHighlighting;
- textOutput = new SmartTextOutput();
- foreach (var node in treeView.SelectedItems.OfType<ILSpyTreeNode>()) {
- textOutput.CurrentTreeNode = node;
- node.Decompile(ILSpy.Language.Current, textOutput);
- }
- referenceElementGenerator.References = textOutput.References;
- textEditor.Text = textOutput.ToString();
- } catch (Exception ex) {
- textEditor.SyntaxHighlighting = null;
- referenceElementGenerator.References = null;
- textEditor.Text = ex.ToString();
- }
+ if (currentCancellationTokenSource != null)
+ currentCancellationTokenSource.Cancel();
+ var myCancellationTokenSource = new CancellationTokenSource();
+ currentCancellationTokenSource = myCancellationTokenSource;
+ var task = RunDecompiler(ILSpy.Language.Current,
+ treeView.SelectedItems.OfType<ILSpyTreeNode>().ToArray(),
+ myCancellationTokenSource.Token);
+ task.ContinueWith(
+ delegate {
+ try {
+ if (currentCancellationTokenSource == myCancellationTokenSource) {
+ currentCancellationTokenSource = null;
+ try {
+ SmartTextOutput textOutput = task.Result;
+ referenceElementGenerator.References = textOutput.References;
+ definitionLookup = textOutput.DefinitionLookup;
+ textEditor.SyntaxHighlighting = ILSpy.Language.Current.SyntaxHighlighting;
+ textEditor.Text = textOutput.ToString();
+ } catch (AggregateException ex) {
+ textEditor.SyntaxHighlighting = null;
+ referenceElementGenerator.References = null;
+ definitionLookup = null;
+ textEditor.Text = string.Join(Environment.NewLine, ex.InnerExceptions.Select(ie => ie.ToString()));
+ }
+ }
+ } finally {
+ myCancellationTokenSource.Dispose();
+ }
+ },
+ TaskScheduler.FromCurrentSynchronizationContext());
+ }
+
+ static Task<SmartTextOutput> RunDecompiler(ILSpy.Language language, ILSpyTreeNode[] nodes, CancellationToken cancellationToken)
+ {
+ return Task.Factory.StartNew(
+ delegate {
+ SmartTextOutput textOutput = new SmartTextOutput();
+ foreach (var node in nodes) {
+ cancellationToken.ThrowIfCancellationRequested();
+ node.Decompile(language, textOutput, cancellationToken);
+ }
+ return textOutput;
+ });
}
internal void JumpToReference(ReferenceSegment referenceSegment)
{
object reference = referenceSegment.Reference;
- if (textOutput != null) {
- int pos = textOutput.GetDefinitionPosition(reference);
+ if (definitionLookup != null) {
+ int pos = definitionLookup.GetDefinitionPosition(reference);
if (pos >= 0) {
textEditor.TextArea.Focus();
textEditor.Select(pos, 0);
@@ -18,6 +18,8 @@
using System;
using System.Text;
+using System.Threading;
+
using ICSharpCode.TreeView;
using Mono.Cecil;
@@ -70,9 +72,9 @@ public MethodTreeNode(MethodDefinition method)
}
}
- public override void Decompile(Language language, ITextOutput output)
+ public override void Decompile(Language language, ITextOutput output, CancellationToken cancellationToken)
{
- language.Decompile(method, output);
+ language.Decompile(method, output, cancellationToken);
}
public override FilterResult Filter(FilterSettings settings)

0 comments on commit 158b10d

Please sign in to comment.