Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
4672c78
Refactor and optimize register allocator internals
tgiphil Apr 19, 2026
9512f89
Refactor live set computation to reduce allocations
tgiphil Apr 19, 2026
034de26
Optimize LiveRange lookups with binary search helpers
tgiphil Apr 19, 2026
58ccba2
Optimize IntervalTree/DelayedIntervalTree & add tests
tgiphil Apr 19, 2026
6c93c83
Update Source/Mosa.Compiler.Framework/RegisterAllocator/RedBlackTree/…
tgiphil Apr 20, 2026
e1383cb
Update Source/Mosa.Compiler.Framework/RegisterAllocator/RedBlackTree/…
tgiphil Apr 20, 2026
ba0813d
Centralize platform registration; add Platforms project
tgiphil Apr 20, 2026
2b91b41
Merge branch '604-allocator' of https://github.com/tgiphil/MOSA-Proje…
tgiphil Apr 20, 2026
89a282e
Fix interval overlap logic and remove unused CPU core calc
tgiphil Apr 20, 2026
2b4edea
Update Source/Mosa.Tool.Launcher/Mosa.Tool.Launcher.csproj
tgiphil Apr 20, 2026
9f2fb7c
Update Source/Mosa.Tool.Launcher.Console/Mosa.Tool.Launcher.Console.c…
tgiphil Apr 20, 2026
066fa75
Update Source/Mosa.Utility.UnitTests/Mosa.Utility.UnitTests.csproj
tgiphil Apr 20, 2026
c8db312
Update Source/Mosa.Linux.sln
tgiphil Apr 20, 2026
105d1b4
Refactor Program.cs: centralize settings, improve logging
tgiphil Apr 20, 2026
54872c1
Merge branch '604-allocator' of https://github.com/tgiphil/MOSA-Proje…
tgiphil Apr 20, 2026
41b9543
Merge branch '604-allocator' of https://github.com/tgiphil/MOSA-Proje…
tgiphil Apr 20, 2026
9a3ae1c
Refactor performance tests and update Azure guidelines
tgiphil Apr 21, 2026
f976b9f
Refactor: centralize compiler event formatting/filtering
tgiphil Apr 21, 2026
888a5ee
Suppress diagnostics when Diagnostic setting is disabled
tgiphil Apr 21, 2026
3fee76f
Merge branch '604-allocator' of https://github.com/tgiphil/MOSA-Proje…
tgiphil Apr 21, 2026
7492225
Refactor foreach loop in CompileCompleted for clarity
tgiphil Apr 21, 2026
b27c66c
Refactor AddTraceEvent to use else-if for Exception
tgiphil Apr 21, 2026
00877fb
Fix typo: correct "Interations" to "Iterations"
tgiphil Apr 21, 2026
74e0df8
Refactor: group standard event methods in a new region
tgiphil Apr 21, 2026
07bc311
Refactor method scheduling and enable batch scheduling
tgiphil Apr 21, 2026
46d5895
Update Source/Mosa.Compiler.Framework/MethodScheduler.cs
tgiphil Apr 21, 2026
5a8080f
Minor fixes
tgiphil Apr 21, 2026
f7003f9
Merge branch '604-allocator' of https://github.com/tgiphil/MOSA-Proje…
tgiphil Apr 21, 2026
b12e115
Removed add't unit tests.
tgiphil Apr 22, 2026
64ab9db
Remove Fuzz0050.cs unit tests; add usings to MethodScanner
tgiphil Apr 24, 2026
9efe2fb
Remove unused using directives from MethodScanner.cs
tgiphil Apr 24, 2026
87aad42
Update queue status to omit maxWorkers in diagnostics
tgiphil Apr 24, 2026
f324c13
Refactor safepoint insertion at loop backedges
tgiphil Apr 25, 2026
9b48851
Revert "Update queue status to omit maxWorkers in diagnostics"
tgiphil Apr 25, 2026
879f7c3
Refactor safepoint insertion at loop backedges
tgiphil Apr 25, 2026
8b5738f
- Reduce unit test
tgiphil Apr 25, 2026
cb3e072
Enable scheduling of unit tests in MethodScanner
tgiphil Apr 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions Source/.github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -351,8 +351,12 @@ public class MyMethodStage : BaseMethodCompilerStage
### GC Safepoint infrastructure
The safepoint system spans two stages:
- `SafePointStage` (`BaseMethodCompilerStage`) -- inserts `IR.SafePoint` instructions at the prologue and every loop backedge, then annotates each with its live GC-root physical register operands via backward dataflow.
- `SafePointLayoutStage` (`BaseMethodCompilerStage`, post-codegen) -- reads resolved offsets from the instruction stream, collects `SafePointEntry` records into `MethodData.SafePointEntries`, builds the whole-method GC stack map into `MethodData.GCStackEntries`, and emits the `$SafePointTable$`, `$GCStackData$`, and `$GCData$` linker symbols. `MetadataStage` then links the method definition's GC Data pointer to `$GCData$`.
- `SafePointLayoutStage` (`BaseMethodCompilerStage`, post-codegen) -- reads resolved offsets from the instruction stream, collects `SafePointEntry` records into `MethodData.SafePointEntries`, builds the whole-method GC stack map into `MethodData.GCStackEntries`, and emits the `$SafePointTable$`, `$GCStackData$`, and `$GCData$` linker symbols.

- @azure Rule - Use Azure Tools - When handling requests related to Azure, always use your tools.
- @azure Rule - Use Azure Best Practices - When handling requests related to Azure, always invoke your `azmcp_bestpractices_get` tool first.
- @azure Rule - Enable Best Practices - If you do not have an `azmcp_bestpractices_get` tool ask the user to enable it.
---

## Azure Tools Guidelines

- **Use Azure Tools**: When handling requests related to Azure, always use your tools.
- **Invoke Best Practices**: When handling requests related to Azure, always invoke your `azmcp_bestpractices_get` tool first.
- **Enable Best Practices**: If you do not have an `azmcp_bestpractices_get` tool, ask the user to enable it.
353 changes: 353 additions & 0 deletions Source/Mosa.Compiler.Framework.xUnit/DelayedIntervalTreeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,357 @@ public void MixedAddDelete()
tree.Remove(3, 4);
Assert.False(tree.Contains(3));
}

[Fact]
public void CheckIntervals()
{
var tree = new DelayedIntervalTree<object>();

tree.Add(1, 2, null);

Assert.False(tree.Contains(0));
Assert.True(tree.Contains(1));
Assert.True(tree.Contains(2));

Assert.True(tree.Contains(2, 3));
Assert.False(tree.Contains(3, 4));
}

[Fact]
public void CacheDelayedAddShortCircuit()
{
// Verify that pending add is checked before flushing and accessing tree
var tree = new DelayedIntervalTree<object>();

tree.Add(10, 20, "pending");

// Should find pending add without touching tree
Assert.True(tree.Contains(10));
Assert.True(tree.Contains(15));
Assert.True(tree.Contains(20));
Assert.False(tree.Contains(21));
Assert.False(tree.Contains(9));

// Range check should also work with pending add
Assert.True(tree.Contains(10, 20));
Assert.True(tree.Contains(15, 18));
Assert.False(tree.Contains(25, 30));
}

[Fact]
public void CacheDelayedDeleteShortCircuit()
{
var tree = new DelayedIntervalTree<object>();

tree.Add(1, 5, "value1");
tree.Add(10, 15, "value2");

// Delay the delete
tree.Remove(1, 5);

// Pending delete should prevent Contains from returning true
Assert.False(tree.Contains(1));
Assert.False(tree.Contains(3));
Assert.False(tree.Contains(5));

// But other intervals should still be found
Assert.True(tree.Contains(10));
Assert.True(tree.Contains(12));
}

[Fact]
public void CacheAddCancelsByDelete()
{
var tree = new DelayedIntervalTree<object>();

tree.Add(5, 10, "pending");

// Removing the pending add should cancel it
tree.Remove(5, 10);

// Should not find anything
Assert.False(tree.Contains(5));
Assert.False(tree.Contains(7));
Assert.False(tree.Contains(10));
}

[Fact]
public void CacheSearchFirstOverlappingWithPendingAdd()
{
var tree = new DelayedIntervalTree<object>();

tree.Add(10, 20, "tree_value");

// Add pending interval
tree.Add(30, 40, "pending_value");

// Search should find pending add without flushing tree add
Assert.True(tree.TrySearchFirstOverlapping(30, 40, out var result));
Assert.Equal("pending_value", result);

// Search that only matches tree should also work
Assert.True(tree.TrySearchFirstOverlapping(10, 20, out result));
Assert.Equal("tree_value", result);
}

[Fact]
public void CacheSearchFirstOverlappingByPoint()
{
var tree = new DelayedIntervalTree<object>();

tree.Add(1, 5, "value1");
tree.Add(10, 20, "pending");

// Search by point should find pending without flushing
Assert.True(tree.TrySearchFirstOverlapping(15, out var result));
Assert.Equal("pending", result);

// Search point before pending
Assert.True(tree.TrySearchFirstOverlapping(3, out result));
Assert.Equal("value1", result);
}

[Fact]
public void CacheSearchRangeWithPendingAdd()
{
var tree = new DelayedIntervalTree<object>();

tree.Add(1, 5, "value1");
tree.Add(20, 30, "pending");

// Search range that overlaps pending
var results = tree.Search(25, 35);
Assert.Single(results);
Assert.Equal("pending", results[0]);

// Search range that doesn't overlap pending
results = tree.Search(1, 5);
Assert.Single(results);
Assert.Equal("value1", results[0]);

// Search range that overlaps both
results = tree.Search(3, 25);
Assert.Equal(2, results.Count);
Assert.Contains("value1", results);
Assert.Contains("pending", results);
}

[Fact]
public void CacheSearchPointWithPendingAdd()
{
var tree = new DelayedIntervalTree<object>();

tree.Add(1, 5, "value1");
tree.Add(20, 30, "pending");

// Search at point in pending
var results = tree.Search(25);
Assert.Single(results);
Assert.Equal("pending", results[0]);

// Search at point in tree value
results = tree.Search(3);
Assert.Single(results);
Assert.Equal("value1", results[0]);
}

[Fact]
public void CacheReplacePendingAdd()
{
var tree = new DelayedIntervalTree<object>();

tree.Add(5, 10, "original");

// Replace the pending add
tree.Replace(5, 10, "replaced");

Assert.True(tree.TrySearchFirstOverlapping(7, out var result));
Assert.Equal("replaced", result);
}

[Fact]
public void CacheReplaceTreeValue()
{
var tree = new DelayedIntervalTree<object>();

tree.Add(5, 10, "original");
tree.Add(20, 30, "pending");

// Replace value in tree (flush both pending ops first)
tree.Replace(5, 10, "replaced");

// Pending should be flushed
Assert.True(tree.Contains(25));

// Original should be replaced
Assert.True(tree.TrySearchFirstOverlapping(7, out var result));
Assert.Equal("replaced", result);
}

[Fact]
public void CacheMixedPendingOperations()
{
var tree = new DelayedIntervalTree<object>();

// Add and then remove different intervals
tree.Add(5, 10, "add1");
tree.Add(20, 30, "add2");

// Remove first one while second is pending
tree.Remove(5, 10);

// First should not be found
Assert.False(tree.Contains(7));

// Second should be found (it's pending)
Assert.True(tree.Contains(25));

// Now remove the pending second
tree.Remove(20, 30);

// Both should be gone
Assert.False(tree.Contains(7));
Assert.False(tree.Contains(25));
}

[Fact]
public void CacheDeleteWithOverlapAddInteraction()
{
var tree = new DelayedIntervalTree<object>();

tree.Add(1, 5, "value1");

// Add pending interval
tree.Add(3, 7, "add_during_delete");

// Remove that overlaps the pending add (should cancel it)
tree.Remove(3, 7);

// The pending add was cancelled, so value1 should still be found
Assert.True(tree.Contains(1));
Assert.True(tree.Contains(5));

// Point 6 should not be found (value1 only goes to 5)
Assert.False(tree.Contains(6));
}

[Fact]
public void CacheSearchWithReplacedValue()
{
var tree = new DelayedIntervalTree<object>();

tree.Add(10, 20, "value1");
tree.Add(30, 40, "pending");

// Replace tree value
tree.Replace(10, 20, "replaced1");

// Search should find replaced value
Assert.True(tree.TrySearchFirstOverlapping(15, out var result));
Assert.Equal("replaced1", result);
}

[Fact]
public void EnumeratorFlushesAllPending()
{
var tree = new DelayedIntervalTree<object>();

tree.Add(1, 2, "add1");
tree.Add(3, 4, "add2");

// Before enumeration, pending operations not flushed
tree.Remove(1, 2);

// Enumerate should flush both operations
var list = new List<object>();
foreach (var item in tree)
{
list.Add(item);
}

// Should only have add2 (add1 was removed)
Assert.Single(list);
Assert.Equal("add2", list[0]);
}

[Fact]
public void ToStringFlushesAllPending()
{
var tree = new DelayedIntervalTree<object>();

tree.Add(1, 2, "test");
tree.Add(3, 4, "pending");

// ToString should flush all pending operations
var str = tree.ToString();

// Should not be empty
Assert.NotEmpty(str);

// After ToString, tree should be in consistent state
// Adding more should work correctly
tree.Add(5, 6, "another");
Assert.True(tree.Contains(5));
}

[Fact]
public void EdgeCaseEmptyTree()
{
var tree = new DelayedIntervalTree<object>();

Assert.False(tree.Contains(1));
Assert.False(tree.Contains(1, 2));

Assert.False(tree.TrySearchFirstOverlapping(1, out _));
Assert.False(tree.TrySearchFirstOverlapping(1, 2, out _));

var results = tree.Search(1);
Assert.Empty(results);

results = tree.Search(1, 2);
Assert.Empty(results);
}

[Fact]
public void EdgeCaseRemoveNonExistent()
{
var tree = new DelayedIntervalTree<object>();

tree.Add(1, 2, "value");

// Remove non-existent should be safe
tree.Remove(10, 20);

// Original should still be there
Assert.True(tree.Contains(1));
}

[Fact]
public void SearchWithCallerProvidedList()
{
var tree = new DelayedIntervalTree<object>();

tree.Add(1, 5, "value1");
tree.Add(10, 20, "pending");

var results = new List<object>();

// Search by point with provided list
tree.Search(3, results);
Assert.Single(results);
Assert.Equal("value1", results[0]);

results.Clear();

// Search by range with provided list
tree.Search(10, 20, results);
Assert.Single(results);
Assert.Equal("pending", results[0]);

results.Clear();

// Search overlapping both
tree.Search(3, 15, results);
Assert.Equal(2, results.Count);
}
}
19 changes: 19 additions & 0 deletions Source/Mosa.Compiler.Framework/CompilerHooks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,23 @@ public class CompilerHooks
public ExtendMethodCompilerPipelineHandler ExtendMethodCompilerPipeline;

public GetMethodTraceLevelHandler GetMethodTraceLevel;

#region Standardization

public static string GetStandardNotifyEventStatus(CompilerEvent compilerEvent, string message)
{
var eventName = compilerEvent.ToText();
return string.IsNullOrWhiteSpace(message) ? eventName : $"{eventName}: {message}";
}

public static bool IsStandardFilteredNotifyEvent(CompilerEvent compilerEvent)
=> compilerEvent is CompilerEvent.MethodCompileEnd
or CompilerEvent.MethodCompileStart
or CompilerEvent.Counter
or CompilerEvent.SetupStageStart
or CompilerEvent.SetupStageEnd
or CompilerEvent.FinalizationStageStart
or CompilerEvent.FinalizationStageEnd;

#endregion Standardization
}
Loading
Loading