Skip to content

Commit

Permalink
Feature: introduced IEventBus, removed high-overhead event generation
Browse files Browse the repository at this point in the history
ImageMap was generating high-frequency events, which were slowing down Reko's GUI. By changing the event firing to only happen when Procedures are discovered, scanner execution time was reduced by 40%.
  • Loading branch information
uxmal committed Jul 31, 2023
1 parent c5ee644 commit a42da99
Show file tree
Hide file tree
Showing 199 changed files with 684 additions and 558 deletions.
2 changes: 1 addition & 1 deletion .ci/linux_arm64/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ RUN apt-get update && \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& dotnet nuget locals all --clear
# reserved for cache eviction: 0
# reserved for cache eviction: 1
4 changes: 2 additions & 2 deletions src/Arch/X86/Analysis/FstswAnalysis.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ namespace Reko.Arch.X86.Analysis
public class FstswAnalysis : IAnalysis<SsaState>
{
private readonly IReadOnlyProgram program;
private readonly DecompilerEventListener listener;
private readonly IEventListener listener;
private SsaState ssa;

public FstswAnalysis(IReadOnlyProgram program, DecompilerEventListener listener)
public FstswAnalysis(IReadOnlyProgram program, IEventListener listener)
{
this.program = program;
this.ssa = default!;
Expand Down
10 changes: 5 additions & 5 deletions src/Core/AddressContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,19 @@ public class AddressContext
{
private readonly Program program;
private readonly Address addr;
private readonly DecompilerEventListener decompilerEventListener;
private readonly IEventListener eventListener;

public AddressContext(Program program, Address addr, DecompilerEventListener decompilerEventListener)
public AddressContext(Program program, Address addr, IEventListener eventListener)
{
this.program = program;
this.addr = addr;
this.decompilerEventListener = decompilerEventListener;
this.eventListener = eventListener;
}

public void Warn(string format, params object [] args)
{
decompilerEventListener.Warn(
decompilerEventListener.CreateAddressNavigator(program, addr),
eventListener.Warn(
eventListener.CreateAddressNavigator(program, addr),
string.Format(format, args));
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Configuration/PlatformDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public void LoadSettingsFromConfiguration(IServiceProvider services, Platform pl
{
var cfgSvc = services.RequireService<IConfigurationService>();
var fsSvc = services.RequireService<IFileSystemService>();
var listener = services.RequireService<DecompilerEventListener>();
var listener = services.RequireService<IEventListener>();
try
{
var filePath = cfgSvc.GetInstallationRelativePath(MemoryMapFile!);
Expand Down
4 changes: 2 additions & 2 deletions src/Core/Configuration/RekoConfigurationService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -436,8 +436,8 @@ public virtual ICollection<RawFileDefinition> GetRawFiles()
var options = new Dictionary<string, object>();
if (model is null)
{
var listener = services.GetService<DecompilerEventListener>() ??
new NullDecompilerEventListener();
var listener = services.GetService<IEventListener>() ??
new NullEventListener();
listener.Warn($"Model '{modelName}' is not defined for architecture '{archLabel}'.");
}
else if (model.Options != null)
Expand Down
4 changes: 2 additions & 2 deletions src/Core/DynamicLinker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,10 @@ public class DynamicLinker : IDynamicLinker
{
private readonly Project project;
private readonly Program program;
private readonly DecompilerEventListener eventListener;
private readonly IEventListener eventListener;
private readonly Dictionary<string, ImageSymbol> localProcs;

public DynamicLinker(Project project, Program program, DecompilerEventListener eventListener)
public DynamicLinker(Project project, Program program, IEventListener eventListener)
{
this.project = project ?? throw new ArgumentNullException(nameof(project));
this.program = program;
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Hll/C/UserSignatureBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public UserSignatureBuilder(Program program)
/// For each procedure, either use a user-supplied signature,
/// or the predefined one.
/// </summary>
public void BuildSignatures(DecompilerEventListener listener)
public void BuildSignatures(IEventListener listener)
{
foreach (var de in program.Procedures)
{
Expand Down
37 changes: 0 additions & 37 deletions src/Core/ImageMap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ namespace Reko.Core
/// </summary>
public class ImageMap
{
public event EventHandler? MapChanged;

public ImageMap(Address addrBase)
{
this.BaseAddress = addrBase ?? throw new ArgumentNullException(nameof(addrBase));
Expand Down Expand Up @@ -67,7 +65,6 @@ public ImageMapItem AddItem(Address addr, ImageMapItem itemNew)
{
// Outside of range.
Items.Add(itemNew.Address, itemNew);
FireMapChanged();
return itemNew;
}
else
Expand All @@ -83,13 +80,11 @@ public ImageMapItem AddItem(Address addr, ImageMapItem itemNew)
itemNew.Size = (uint)(item.Size - delta);
item.Size = (uint)delta;
Items.Add(itemNew.Address, itemNew);
FireMapChanged();
return itemNew;
}
else
{
Items.Add(itemNew.Address, itemNew);
FireMapChanged();
return itemNew;
}
}
Expand All @@ -102,15 +97,13 @@ public ImageMapItem AddItem(Address addr, ImageMapItem itemNew)
item.Address += itemNew.Size;
Items[itemNew.Address] = itemNew;
Items[item.Address] = item;
FireMapChanged();
return itemNew;
}
if (item.GetType() != itemNew.GetType()) //$BUGBUG: replaces the type.
{
Items[itemNew.Address] = itemNew;
itemNew.Size = item.Size;
}
FireMapChanged();
return item;
}
}
Expand Down Expand Up @@ -180,7 +173,6 @@ public void AddItemWithSize(Address addr, ImageMapItem itemNew)
Items.Add(addr, itemNew);
}
}
FireMapChanged();
}

public ImageMap Clone()
Expand Down Expand Up @@ -256,8 +248,6 @@ nextItem.DataType is UnknownType &&
mergedItem.Size = (uint)(nextItem.EndAddress - mergedItem.Address);
Items.Remove(nextItem.Address);
}

FireMapChanged();
}

/// <summary>
Expand All @@ -282,33 +272,6 @@ public bool TryFindItemExact(Address addr, out ImageMapItem item)
return Items.TryGetValue(addr, out item);
}

//$TODO: the following code is a stopgap to prevent unnecessary reloading
// of the user interface during background operations. In the future,
// Reko will need to handle this in a better way, but the changes required
// are rather large. See GitHub [issue #567](https://github.com/uxmal/reko/issues/567)
// for the gory details.
private bool mapChangedEventHandlerPaused;
private bool mapChangedPendingEvents;

private void FireMapChanged()
{
if (!mapChangedEventHandlerPaused) MapChanged?.Invoke(this, EventArgs.Empty);
else mapChangedPendingEvents = true;
}

public void PauseEventHandler()
{
mapChangedEventHandlerPaused = true;
}

public void UnpauseEventHandler()
{
mapChangedEventHandlerPaused = false;
if (mapChangedPendingEvents) MapChanged?.Invoke(this, EventArgs.Empty);
mapChangedPendingEvents = false;
}


// class ItemComparer //////////////////////////////////////////////////

private class ItemComparer : IComparer<Address>
Expand Down
6 changes: 3 additions & 3 deletions src/Core/Output/GlobalDataWriter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ private void WriteGlobalVariable(StructureField field)
}
catch (Exception ex)
{
var dc = services.RequireService<DecompilerEventListener>();
var dc = services.RequireService<IEventListener>();
dc.Error(
dc.CreateAddressNavigator(program, addr),
ex,
Expand Down Expand Up @@ -156,7 +156,7 @@ public void WriteGlobalVariable(Address address, DataType dataType, string name)
}
catch (Exception ex)
{
var dc = services.RequireService<DecompilerEventListener>();
var dc = services.RequireService<IEventListener>();
dc.Error(
dc.CreateAddressNavigator(program, address),
ex,
Expand Down Expand Up @@ -198,7 +198,7 @@ public CodeFormatter VisitArray(ArrayType at)
{
if (at.Length == 0)
{
var dc = services.RequireService<DecompilerEventListener>();
var dc = services.RequireService<IEventListener>();
dc.Warn(
dc.CreateAddressNavigator(program, rdr.Address),
"Expected sizes of arrays to have been determined by now");
Expand Down
4 changes: 2 additions & 2 deletions src/Core/Output/GlobalObjectTracer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ public class GlobalObjectTracer : IDataTypeVisitor<int>
private readonly HashSet<Address> visited;
private readonly DataTypeComparer cmp;
private readonly StructureFieldCollection globalFields;
private readonly DecompilerEventListener eventListener;
private readonly IEventListener eventListener;
private int recursionGuard;
private EndianImageReader rdr;

public GlobalObjectTracer(Program program, WorkList<(StructureField, Address)> wl, DecompilerEventListener eventListener)
public GlobalObjectTracer(Program program, WorkList<(StructureField, Address)> wl, IEventListener eventListener)
{
this.program = program;
this.wl = wl;
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Output/OutputFilePolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public OutputFilePolicy(Program program)
/// <returns></returns>
public abstract Dictionary<string, IDictionary<Address, IAddressable>> GetObjectPlacements(
string fileExtension,
DecompilerEventListener listener);
IEventListener listener);

/// <summary>
/// Returns a placement mapping for rendering low-level items.
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Output/SegmentFilePolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public SegmentFilePolicy(Program program) : base(program)

public override Dictionary<string, IDictionary<Address, IAddressable>> GetObjectPlacements(
string fileExtension,
DecompilerEventListener listener)
IEventListener listener)
{
Debug.Assert(fileExtension.Length > 0 && fileExtension[0] == '.');

Expand Down
2 changes: 1 addition & 1 deletion src/Core/Output/SingleFilePolicy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public SingleFilePolicy(Program program) : base(program)
this.defaultDataFile = "";
}

public override Dictionary<string, IDictionary<Address, IAddressable>> GetObjectPlacements(string fileExtension, DecompilerEventListener listener)
public override Dictionary<string, IDictionary<Address, IAddressable>> GetObjectPlacements(string fileExtension, IEventListener listener)
{
this.defaultFile = Path.ChangeExtension(program.Name, fileExtension);
this.defaultDataFile = Path.ChangeExtension(program.Name, "globals" + fileExtension);
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Platform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ public TypeLibrary CreateMetadata()
{
if (this.MemoryMap == null || this.MemoryMap.Segments == null)
return null;
var listener = Services.RequireService<DecompilerEventListener>();
var listener = Services.RequireService<IEventListener>();
var segs = MemoryMap.Segments.Select(s => MemoryMap_v1.LoadSegment(s, this, listener))
.Where(s => s != null)
.ToSortedList(s => s!.Address, s => s!);
Expand Down
2 changes: 1 addition & 1 deletion src/Core/Serialization/MemoryMap_v1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public class MemoryMap_v1
return mmap;
}

public static ImageSegment? LoadSegment(MemorySegment_v1 segment, IPlatform platform, DecompilerEventListener listener)
public static ImageSegment? LoadSegment(MemorySegment_v1 segment, IPlatform platform, IEventListener listener)
{
if (segment.Name is null)
{
Expand Down
6 changes: 3 additions & 3 deletions src/Core/Serialization/ProjectLoader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,15 @@ public class ProjectLoader : ProjectPersister

private readonly ILoader loader;
private readonly Project project;
private readonly DecompilerEventListener listener;
private readonly IEventListener listener;
private IPlatform? platform;
private IProcessorArchitecture? arch;

public ProjectLoader(
IServiceProvider services,
ILoader loader,
ImageLocation location,
DecompilerEventListener listener)
IEventListener listener)
: this(services, loader, new Project(location), listener)
{
}
Expand All @@ -64,7 +64,7 @@ public ProjectLoader(
IServiceProvider services,
ILoader loader,
Project project,
DecompilerEventListener listener)
IEventListener listener)
: base(services)
{
this.loader = loader;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@
namespace Reko.Core.Services
{
/// <summary>
/// This interface is used by the worker thread to communicate with the
/// This interface is used by low-level code to communicate with the
/// driver, be it a command line or a GUI.
/// </summary>
public interface DecompilerEventListener
public interface IEventListener
{
IProgressIndicator Progress { get; }

Expand Down Expand Up @@ -63,14 +63,20 @@ public interface DecompilerEventListener
void Error(ICodeLocation location, Exception ex, string message, params object[] args);
void Error(ScriptError scriptError);

/// <summary>
/// This method is called to determine whether the caller should quit
/// gracefully.
/// </summary>
/// <returns>True if cancellation has been requested, false if not.
/// </returns>
bool IsCanceled();
}

public class NullDecompilerEventListener : DecompilerEventListener
public class NullEventListener : IEventListener
{
public static DecompilerEventListener Instance { get; } = new NullDecompilerEventListener();
public static IEventListener Instance { get; } = new NullEventListener();

#region DecompilerEventListener Members
#region IEventListener Members

public IProgressIndicator Progress => NullProgressIndicator.Instance;

Expand Down
4 changes: 2 additions & 2 deletions src/Core/Services/ITypeLibraryLoaderService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ public TypeLibrary LoadMetadataIntoLibrary(IPlatform platform, TypeLibraryDefini
{
var cfgSvc = services.RequireService<IConfigurationService>();
var fsSvc = services.RequireService<IFileSystemService>();
var listener = services.RequireService<DecompilerEventListener>();
var listener = services.RequireService<IEventListener>();
try
{
if (tlElement.Name == null)
Expand Down Expand Up @@ -90,7 +90,7 @@ public TypeLibrary LoadMetadataIntoLibrary(IPlatform platform, TypeLibraryDefini
else
{
var cfgSvc = services.RequireService<IConfigurationService>();
var listener = services.RequireService<DecompilerEventListener>();
var listener = services.RequireService<IEventListener>();
var ldrElement = cfgSvc.GetImageLoader(tlElement.Loader!);
if (ldrElement != null && !string.IsNullOrEmpty(ldrElement.TypeName))
{
Expand Down
7 changes: 4 additions & 3 deletions src/Decompiler/Analysis/AdjacentBranchCollector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
using Reko.Core.Diagnostics;
using Reko.Core.Expressions;
using Reko.Core.Services;
using Reko.Services;
using System.Diagnostics;
using System.Linq;

Expand Down Expand Up @@ -68,10 +69,10 @@ public class AdjacentBranchCollector
private static readonly TraceSwitch trace = new (nameof(AdjacentBranchCollector), nameof(AdjacentBranchCollector)) { Level = TraceLevel.Error };

private readonly Procedure proc;
private readonly DecompilerEventListener listener;
private readonly IDecompilerEventListener listener;
private readonly ExpressionValueComparer cmp;

public static void Transform(Program program, DecompilerEventListener eventListener)
public static void Transform(Program program, IDecompilerEventListener eventListener)
{
foreach (var proc in program.Procedures.Values)
{
Expand All @@ -82,7 +83,7 @@ public static void Transform(Program program, DecompilerEventListener eventListe
}
}

public AdjacentBranchCollector(Procedure proc, DecompilerEventListener listener)
public AdjacentBranchCollector(Procedure proc, IDecompilerEventListener listener)
{
this.proc = proc;
this.listener = listener;
Expand Down
Loading

0 comments on commit a42da99

Please sign in to comment.