Many speed-ups for profiler generation. Especially scope resolution

This commit is contained in:
Adrian Conlon 2024-06-06 15:11:26 +01:00
parent 35ea9c7b7d
commit 71ce8cde51
5 changed files with 168 additions and 18 deletions

View File

@ -1,4 +1,6 @@
namespace EightBit
#define FAST_ID_LOOKUP
namespace EightBit
{
namespace Files
{
@ -6,10 +8,22 @@
{
public class IdentifiableSection : Section
{
#if FAST_ID_LOOKUP
public int ID { get; private set; }
#else
public int ID => this.TakeInteger("id");
#endif
protected IdentifiableSection() => _ = this._integer_keys.Add("id");
#if FAST_ID_LOOKUP
public override void Parse(Parser parent, Dictionary<string, string> entries)
{
base.Parse(parent, entries);
this.ID = this.TakeInteger("id");
}
#endif
#region Foreign key constraints
#region Generic FK access

View File

@ -1,4 +1,6 @@
namespace EightBit
#define FAST_NAME_LOOKUP
namespace EightBit
{
namespace Files
{
@ -6,9 +8,21 @@
{
public class NamedSection : IdentifiableSection
{
#if FAST_NAME_LOOKUP
public string? Name { get; private set; }
#else
public string Name => this.TakeString("name");
#endif
protected NamedSection() => _ = this._string_keys.Add("name");
#if FAST_NAME_LOOKUP
public override void Parse(Parser parent, Dictionary<string, string> entries)
{
base.Parse(parent, entries);
this.Name = this.TakeString("name");
}
#endif
}
}
}

View File

@ -1,4 +1,7 @@
namespace EightBit
#define BINARY_SCOPE_SEARCH
//#define LINEAR_SCOPE_SEARCH
namespace EightBit
{
namespace Files
{
@ -36,6 +39,9 @@
public Dictionary<int, List<Symbol>> Addresses { get; } = [];
public Dictionary<int, List<Symbol>> Constants { get; } = [];
// Scope clarification
public List<Scope> AddressableScopes { get; } = [];
#endregion
#region Lookups
@ -143,25 +149,83 @@
return null;
}
private static Tuple<int, int> AddressRange(Scope scope)
{
var symbol = scope.Symbol ?? throw new ArgumentOutOfRangeException(nameof(scope), "Non-addressable scope used");
var start = symbol.Value;
return Tuple.Create(start, start + scope.Size - 1);
}
private static bool AddressContained(int address, int start, int end) => (address >= start) && (address <= end);
private static bool AddressContained(int address, Tuple<int, int>? range)
{
if (range == null)
{
return false;
}
var (start, end) = range;
return AddressContained(address, start, end);
}
private static bool AddressContained(int address, Scope scope) => AddressContained(address, AddressRange(scope));
#if BINARY_SCOPE_SEARCH
private int LocateScope(int address)
{
var low = 0;
var high = this.AddressableScopes.Count - 1;
while (low <= high)
{
var mid = low + (high - low) / 2;
var scope = this.AddressableScopes[mid];
var range = AddressRange(scope);
if (AddressContained(address, range))
{
return mid;
}
var (_, end) = range;
// If x greater, ignore left half
if (end < address)
{
low = mid + 1;
}
// If x is smaller, ignore right half
else
{
high = mid - 1;
}
}
// If we reach here, then element was not present
return -1;
}
#endif
public Scope? LookupScope(int address)
{
foreach (var scope in this.Scopes)
#if BINARY_SCOPE_SEARCH
var index = this.LocateScope(address);
return index == -1 ? null : this.AddressableScopes[index];
#endif
#if LINEAR_SCOPE_SEARCH
foreach (var scope in this.AddressableScopes)
{
var symbol = scope.Symbol;
if (symbol != null)
if (AddressContained(address, scope))
{
var symbolAddress = symbol.Value;
var size = scope.Size;
if ((address >= symbolAddress) && (address < symbolAddress + size))
{
return scope;
}
return scope;
}
}
return null;
#endif
}
#endregion
#endregion
#region Scope evaluation
@ -233,7 +297,7 @@
#endregion
#endregion
#endregion
#region Metadata lookup
@ -330,6 +394,23 @@
this.ExtractTypes();
this.Parsed = true;
this.BuildAddressableScopes();
}
private void BuildAddressableScopes()
{
if (!this.Parsed)
{
throw new InvalidOperationException("Fully parsed scopes are unavailable");
}
foreach (var scope in this.Scopes)
{
if (scope.Symbol != null)
{
this.AddressableScopes.Add(scope);
}
}
}
private void ParseLine(string[] elements)

View File

@ -1,4 +1,7 @@
namespace EightBit
#define FAST_SYMBOL_LOOKUP
#define FAST_SIZE_LOOKUP
namespace EightBit
{
namespace Files
{
@ -13,12 +16,32 @@
public string? Type => this.MaybeTakeString("type");
#if FAST_SIZE_LOOKUP
public int Size;
#else
public int Size => this.TakeInteger("size");
#endif
public Scope? Parent => this.MaybeTakeParentReference();
#if FAST_SYMBOL_LOOKUP
private bool _symbolAvailable;
private Symbols.Symbol? _symbol;
public Symbols.Symbol? Symbol
{
get
{
if (!this._symbolAvailable)
{
this._symbol = this.MaybeTakeSymbolReference();
this._symbolAvailable = true;
}
return this._symbol;
}
}
#else
public Symbols.Symbol? Symbol => this.MaybeTakeSymbolReference();
#endif
public List<Span> Spans => this.TakeSpanReferences();
public Scope()
@ -30,6 +53,15 @@
_ = this._integer_keys.Add("sym");
_ = this._multiple_keys.Add("span");
}
#if FAST_SIZE_LOOKUP
public override void Parse(Parser parent, Dictionary<string, string> entries)
{
base.Parse(parent, entries);
this.Size = this.TakeInteger("size");
}
#endif
}
}
}

View File

@ -1,4 +1,6 @@
namespace EightBit
#define FAST_VALUE_LOOKUP
namespace EightBit
{
namespace Files
{
@ -19,7 +21,11 @@
public List<Line> References => this.TakeLineReferences("ref"); // Guess
#if FAST_VALUE_LOOKUP
public int Value;
#else
public int Value => this.TakeInteger("val");
#endif
public Symbols.Segment Segment => this.TakeSegmentReference();
@ -37,9 +43,12 @@
_ = this._enumeration_keys.Add("type");
}
public override void Parse(Parser parent, Dictionary<string, string> entries)
public override void Parse(Parser parent, Dictionary<string, string> entries)
{
base.Parse(parent, entries);
#if FAST_VALUE_LOOKUP
this.Value = this.TakeInteger("val");
#endif
if (this.Type is "lab")
{
this._parent?.AddLabel(this);