Browse Source

Move decompilation to background thread.

pull/1/head
Daniel Grunwald 15 years ago
parent
commit
158b10d2fb
  1. 6
      ICSharpCode.Decompiler/FlowAnalysis/ControlFlowGraph.cs
  2. 10
      ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs
  3. 3
      ILSpy/Decompiler/CSharpLanguage.cs
  4. 10
      ILSpy/Disassembler/ILLanguage.cs
  5. 4
      ILSpy/ILSpyTreeNode.cs
  6. 36
      ILSpy/ITextOutput.cs
  7. 11
      ILSpy/Language.cs
  8. 68
      ILSpy/MainWindow.xaml.cs
  9. 6
      ILSpy/MethodTreeNode.cs

6
ICSharpCode.Decompiler/FlowAnalysis/ControlFlowGraph.cs

@ -23,7 +23,7 @@ using System.Diagnostics; @@ -23,7 +23,7 @@ using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using Mono.Cecil.Cil;
namespace ICSharpCode.Decompiler.FlowAnalysis
@ -97,7 +97,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -97,7 +97,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
}
}
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 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -108,6 +108,8 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
changed = false;
ResetVisited();
cancellationToken.ThrowIfCancellationRequested();
// for all nodes b except the entry point
EntryPoint.TraversePreOrder(
b => b.Successors,

10
ICSharpCode.Decompiler/FlowAnalysis/ControlStructureDetector.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
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 @@ -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 @@ namespace ICSharpCode.Decompiler.FlowAnalysis @@ -111,12 +112,13 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
#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)

3
ILSpy/Decompiler/CSharpLanguage.cs

@ -18,6 +18,7 @@ @@ -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 @@ namespace ICSharpCode.ILSpy.Decompiler @@ -34,7 +35,7 @@ namespace ICSharpCode.ILSpy.Decompiler
get { return "C#"; }
}
public override void Decompile(MethodDefinition method, ITextOutput output)
public override void Decompile(MethodDefinition method, ITextOutput output, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}

10
ILSpy/Disassembler/ILLanguage.cs

@ -19,6 +19,8 @@ @@ -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 @@ namespace ICSharpCode.ILSpy.Disassembler @@ -36,10 +38,10 @@ namespace ICSharpCode.ILSpy.Disassembler
}
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 @@ namespace ICSharpCode.ILSpy.Disassembler @@ -66,9 +68,9 @@ namespace ICSharpCode.ILSpy.Disassembler
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) {

4
ILSpy/ILSpyTreeNode.cs

@ -20,6 +20,8 @@ using System; @@ -20,6 +20,8 @@ using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Threading;
using ICSharpCode.TreeView;
namespace ICSharpCode.ILSpy
@ -52,7 +54,7 @@ namespace ICSharpCode.ILSpy @@ -52,7 +54,7 @@ namespace ICSharpCode.ILSpy
return FilterResult.Hidden;
}
public virtual void Decompile(Language language, ITextOutput output)
public virtual void Decompile(Language language, ITextOutput output, CancellationToken cancellationToken)
{
}
}

36
ILSpy/ITextOutput.cs

@ -38,22 +38,11 @@ namespace ICSharpCode.ILSpy @@ -38,22 +38,11 @@ namespace ICSharpCode.ILSpy
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 @@ namespace ICSharpCode.ILSpy @@ -64,6 +53,25 @@ namespace ICSharpCode.ILSpy
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 @@ namespace ICSharpCode.ILSpy @@ -118,7 +126,7 @@ namespace ICSharpCode.ILSpy
{
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 @@ namespace ICSharpCode.ILSpy @@ -127,7 +135,7 @@ namespace ICSharpCode.ILSpy
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 });
}
}
}

11
ILSpy/Language.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Threading;
using Mono.Cecil;
namespace ICSharpCode.ILSpy
@ -34,23 +35,23 @@ namespace ICSharpCode.ILSpy @@ -34,23 +35,23 @@ namespace ICSharpCode.ILSpy
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)
{
}

68
ILSpy/MainWindow.xaml.cs

@ -17,15 +17,19 @@ @@ -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 @@ namespace ICSharpCode.ILSpy @@ -210,31 +214,61 @@ namespace ICSharpCode.ILSpy
}
}
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);

6
ILSpy/MethodTreeNode.cs

@ -18,6 +18,8 @@ @@ -18,6 +18,8 @@
using System;
using System.Text;
using System.Threading;
using ICSharpCode.TreeView;
using Mono.Cecil;
@ -70,9 +72,9 @@ namespace ICSharpCode.ILSpy @@ -70,9 +72,9 @@ namespace ICSharpCode.ILSpy
}
}
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)

Loading…
Cancel
Save