Skip to content

Refactor and optimize register allocator and live set computations - #1288

Merged
tgiphil merged 37 commits into
mosa:masterfrom
tgiphil:604-allocator
Apr 25, 2026
Merged

tgiphil merged 37 commits into
mosa:masterfrom
tgiphil:604-allocator

Conversation

@tgiphil

@tgiphil tgiphil commented Apr 19, 2026

Copy link
Copy Markdown
Member

No description provided.

tgiphil added 4 commits April 19, 2026 10:49
Renamed KillSite to KillSites for clarity, replaced linear search with binary search in FindKillAllSite for better performance, and updated GetVirtualRegisters to skip physical registers. Improved GetRegisterMoves by indexing intervals by start slot and replaced break with continue for more accurate control flow. These changes enhance efficiency and maintainability of the register allocator.
Refactored ComputeGlobalLiveSets to reuse BitArray instances for liveOut and liveIn, resetting and updating them in place instead of allocating new arrays per block. Improved change detection logic to update only when necessary, reducing memory usage and improving efficiency.
Refactored use/def position lookups in LiveRange to use binary search methods, improving performance for large lists. Added GetPreviousUse and GetPreviousDef methods. Helper methods are implemented as private static functions.
Refactored DelayedIntervalTree to delay add/remove operations and short-circuit queries, reducing tree manipulations. Added extensive unit tests for edge cases and pending operation logic. IntervalTree now uses loops instead of recursion for search/insertion and MaxEnd updates, improving performance and stack usage. Added overloads for search methods to reduce allocations and new TrySearchFirstOverlapping methods. Improved documentation and ensured no unsafe or auto-generated code was modified.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors and optimizes several hot paths in the register allocator, primarily around interval tree querying, live-set computation, and live-range position lookups, with additional unit tests added for the delayed interval tree wrapper.

Changes:

  • Added allocation-free interval tree search overloads and TrySearchFirstOverlapping APIs; reduced recursion and improved MaxEnd maintenance logic.
  • Optimized register allocator live-set computation, kill-site lookup, and move-resolution interval lookups.
  • Expanded xUnit coverage for DelayedIntervalTree and adjusted scheduler queue status logging output.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
Source/Mosa.Compiler.Framework/RegisterAllocator/RedBlackTree/IntervalTree.cs Adds allocation-free search overloads, TrySearchFirstOverlapping, iterative subtree search, and MaxEnd update refactors.
Source/Mosa.Compiler.Framework/RegisterAllocator/RedBlackTree/DelayedIntervalTree.cs Adds short-circuit logic for pending ops, TrySearchFirstOverlapping, allocation-free search overloads, and a ToString() override.
Source/Mosa.Compiler.Framework/RegisterAllocator/LiveRange.cs Replaces linear scans with binary searches for next/previous def/use lookups and adds helper search routines.
Source/Mosa.Compiler.Framework/RegisterAllocator/BaseRegisterAllocator.cs Reuses BitArray buffers for global live sets, renames/optimizes kill-site handling, improves virtual-register enumeration, and accelerates move lookup via indexing by start.
Source/Mosa.Compiler.Framework/MethodScheduler.cs Simplifies queue status CPU logging output.
Source/Mosa.Compiler.Framework.xUnit/DelayedIntervalTreeTests.cs Adds extensive tests covering pending add/delete behavior, searching, replace behavior, enumeration flushing, and caller-provided result lists.
Comments suppressed due to low confidence (1)

Source/Mosa.Compiler.Framework/RegisterAllocator/RedBlackTree/DelayedIntervalTree.cs:111

  • In Remove(...), cancellation of a pending add uses endpoint containment checks. If the removal range fully contains the pending add interval, neither endpoint may be inside the pending interval and the pending add won’t be cancelled, even though Remove will later remove the overlapping interval in the underlying IntervalTree. Consider using Overlaps(...) (or explicit equality if Remove is intended to only target exact intervals).
		// If pending add overlaps, cancel it
		if (delayedAdd && (Contains(delayedAddStart, delayedAddEnd, start) || Contains(delayedAddStart, delayedAddEnd, end)))
		{
			delayedAdd = false;
			return;
		}

Comment thread Source/Mosa.Compiler.Framework/RegisterAllocator/RedBlackTree/IntervalTree.cs Outdated
Comment thread Source/Mosa.Compiler.Framework/RegisterAllocator/RedBlackTree/IntervalTree.cs Outdated
tgiphil and others added 5 commits April 19, 2026 20:48
…DelayedIntervalTree.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Phil Garcia <phil@thinkedge.com>
…DelayedIntervalTree.cs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Phil Garcia <phil@thinkedge.com>
Replaces reflection-based platform registration with explicit, centralized registration via PlatformRegistrations.Register(). Adds new Mosa.Compiler.Platforms project and updates all relevant .csproj and solution files to reference it. Updates PlatformRegistry to remove assembly scanning. Includes minor code cleanups and adds x64 build configs to Mosa.Linux.sln.
- Remove unused equivalent CPU core calculation in ReportQueueStatus.
- Use Overlaps method for correct interval overlap detection in DelayedIntervalTree.Add.
- Fix off-by-one errors in IntervalTree by changing MaxEnd > to MaxEnd >= in search logic.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 26 out of 28 changed files in this pull request and generated 4 comments.

Comment thread Source/Mosa.Compiler.Framework/MethodScheduler.cs
Comment thread Source/Mosa.Tool.Launcher/Mosa.Tool.Launcher.csproj Outdated
Comment thread Source/Mosa.Tool.Launcher.Console/Mosa.Tool.Launcher.Console.csproj Outdated
Comment thread Source/Mosa.Utility.UnitTests/Mosa.Utility.UnitTests.csproj Outdated
tgiphil and others added 3 commits April 19, 2026 21:48
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Phil Garcia <phil@thinkedge.com>
…sproj

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Phil Garcia <phil@thinkedge.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Phil Garcia <phil@thinkedge.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 26 out of 28 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (3)

Source/Mosa.Compiler.Framework/RegisterAllocator/RedBlackTree/IntervalTree.cs:520

  • IntervalTree.Replace() writes to the node returned by FindInterval without checking for Sentinel. If the interval isn’t present, FindInterval returns Sentinel and this assignment mutates the Sentinel’s Value, which can break future searches/operations. Replace should either no-op or throw when the interval doesn’t exist (and avoid writing to Sentinel).
	public void Replace(int start, int end, T value)
	{
		var node = FindInterval(Root, new Interval(start, end));
		node.Value = value;
	}

Source/Mosa.Compiler.Framework/MethodScheduler.cs:399

  • CalculateCpuUsage(): removing the try/catch means any exception from Process.Refresh()/TotalProcessorTime (platform-specific failures, disposed process, permission issues, etc.) will now propagate out of diagnostic reporting and can crash compilation. Please reintroduce exception handling (or otherwise harden this path) so diagnostics can’t take down the compiler.
	private double CalculateCpuUsage(long currentTicks)
	{
		currentProcess.Refresh();
		var currentCpuTime = currentProcess.TotalProcessorTime;
		var cpuTimeDelta = (currentCpuTime - lastCpuTime).TotalMilliseconds;

		var ticksDelta = currentTicks - lastCpuCheckTicks;
		var wallTimeDelta = (ticksDelta / (double)Stopwatch.Frequency) * 1000.0; // Convert to milliseconds

		lastCpuTime = currentCpuTime;
		lastCpuCheckTicks = currentTicks;

		if (wallTimeDelta > 0 && wallTimeDelta < 60000) // Sanity check: < 60 seconds
		{
			// CPU percentage divided by cores to match Task Manager (0-100% scale)
			var cpuPercent = (cpuTimeDelta / wallTimeDelta / processorCount) * 100.0;
			return Math.Clamp(cpuPercent, 0.0, 100.0);
		}

		return 0.0;
	}

Source/Mosa.Compiler.Framework/RegisterAllocator/RedBlackTree/DelayedIntervalTree.cs:111

  • Remove(): the pending-add cancellation check only tests whether the endpoints of the remove range fall inside the pending add interval. If the remove range fully covers the pending add (e.g., pending [10,20], remove [5,25]), the pending add will not be cancelled and the tree can report incorrect results. Use a true overlap test (like the Overlaps helper) for this condition.
	public void Remove(int start, int end)
	{
		// If pending add overlaps, cancel it
		if (delayedAdd && (Contains(delayedAddStart, delayedAddEnd, start) || Contains(delayedAddStart, delayedAddEnd, end)))
		{
			delayedAdd = false;
			return;
		}

Comment thread Source/Mosa.Linux.sln Outdated
tgiphil and others added 5 commits April 19, 2026 23:15
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Phil Garcia <phil@thinkedge.com>
Refactored Program.cs to use static MosaSettings and Stopwatch instances, centralizing settings logic into SetRequiredSettings and UpdateSettings methods. The compile process now benchmarks multiple methods in Mosa.UnitTests.Fuzzy.Fuzz0009 and outputs timing for each via a new OutputStatus method with elapsed time prefixes. Increased default compile iterations from 10 to 100. Fuzz0009.cs changes are whitespace-only (CR removal, reformatting) with no logic modifications.
… into 604-allocator

Enable multithreaded compilation for fuzzy test methods

Switch to multithreaded compilation by setting MosaSettings.Multithreading and MaxThreads, and enable method scanning and diagnostics. Replace hardcoded method compilation with dynamic collection and scheduling of up to 2000 fuzzy test methods. Add GetFuzzyMethods helper to gather relevant methods, and improve status output to reflect method count and thread usage.
Refactored Program.cs to separate single and multithreaded performance tests, reduced fuzz method count, and improved compiler hook event handling. Updated status messages and moved platform registration to its own method. Revised Azure Tools Guidelines in copilot-instructions.md for clarity. Set MethodScanner to false.
tgiphil added 3 commits April 20, 2026 20:42
Refactored the foreach loop in the CompileCompleted method to use explicit braces, improving readability. No functional changes were introduced.
Changed AddTraceEvent to handle CompilerEvent.Exception with an else-if instead of a separate if. This ensures the Exception and Error cases are mutually exclusive and prevents both log blocks from executing for the same event.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 31 out of 34 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (1)

Source/Mosa.Compiler.Framework/RegisterAllocator/RedBlackTree/DelayedIntervalTree.cs:111

  • Remove(start, end) is intended to cancel a pending add when the remove range overlaps it, but the current check only tests whether the remove start/end points fall inside the pending add. This misses cases like pending add [5,10] followed by remove [0,20], leaving delayedAdd active and causing subsequent Contains/Search calls to return results that should have been removed. Consider using the existing Overlaps(...) helper (or an equivalent overlap check) here as well.
	public void Remove(int start, int end)
	{
		// If pending add overlaps, cancel it
		if (delayedAdd && (Contains(delayedAddStart, delayedAddEnd, start) || Contains(delayedAddStart, delayedAddEnd, end)))
		{
			delayedAdd = false;
			return;
		}

Comment thread Source/Mosa.Compiler.Platforms/PlatformRegistrations.cs
Comment thread Source/Mosa.Workspace.Experiment.Debug/Program.cs Outdated
tgiphil added 3 commits April 20, 2026 21:23
Corrected a typo in the compile time measurement output message,
changing "Interations" to "Iterations" for clarity.
Moved GetStandardNotifyEventStatus and IsStandardFilteredNotifyEvent into a new #region Standardization within CompilerHooks for better code organization. No functional changes were made.
Refactored MethodScanner to extract entry point and required type scheduling into separate methods for clarity. Added overloads to MethodScheduler and MosaCompiler to support batch scheduling of methods, improving performance in multithreaded fuzz tests. Changed MethodScanner default to enabled in settings. Cleaned up initialization logic for better maintainability.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 34 out of 37 changed files in this pull request and generated 6 comments.

Comments suppressed due to low confidence (1)

Source/Mosa.Compiler.Framework/RegisterAllocator/RedBlackTree/DelayedIntervalTree.cs:111

  • Remove(int start, int end) says it cancels a pending add when it overlaps, but the condition only checks whether the remove range endpoints fall inside the pending add. This misses overlap cases where the pending add is strictly contained within the remove range. Use the same overlap predicate used elsewhere (e.g., Overlaps(delayedAddStart, delayedAddEnd, start, end)) so pending adds are reliably canceled for any overlap.
	public void Remove(int start, int end)
	{
		// If pending add overlaps, cancel it
		if (delayedAdd && (Contains(delayedAddStart, delayedAddEnd, start) || Contains(delayedAddStart, delayedAddEnd, end)))
		{
			delayedAdd = false;
			return;
		}

Comment on lines +434 to +443
private void ScheduledEntryPoint()
{
var entryPoint = TypeSystem.EntryPoint;

if (entryPoint != null)
{
MarkMethodInvoked(entryPoint);
ScheduleMethod(entryPoint);
}
}

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ScheduledEntryPoint() name reads like a past-tense state but it performs an action (scheduling). Renaming to ScheduleEntryPoint() would better match intent and the naming of ScheduleRequiredMethods() below.

Copilot uses AI. Check for mistakes.
Comment thread Source/Mosa.Compiler.Framework/MethodScheduler.cs Outdated
Comment on lines 408 to 425
private double CalculateCpuUsage(long currentTicks)
{
try
{
currentProcess.Refresh();
var currentCpuTime = currentProcess.TotalProcessorTime;
var cpuTimeDelta = (currentCpuTime - lastCpuTime).TotalMilliseconds;
currentProcess.Refresh();
var currentCpuTime = currentProcess.TotalProcessorTime;
var cpuTimeDelta = (currentCpuTime - lastCpuTime).TotalMilliseconds;

var ticksDelta = currentTicks - lastCpuCheckTicks;
var wallTimeDelta = (ticksDelta / (double)Stopwatch.Frequency) * 1000.0; // Convert to milliseconds
var ticksDelta = currentTicks - lastCpuCheckTicks;
var wallTimeDelta = (ticksDelta / (double)Stopwatch.Frequency) * 1000.0; // Convert to milliseconds

lastCpuTime = currentCpuTime;
lastCpuCheckTicks = currentTicks;
lastCpuTime = currentCpuTime;
lastCpuCheckTicks = currentTicks;

if (wallTimeDelta > 0 && wallTimeDelta < 60000) // Sanity check: < 60 seconds
{
// CPU percentage divided by cores to match Task Manager (0-100% scale)
var cpuPercent = (cpuTimeDelta / wallTimeDelta / processorCount) * 100.0;
return Math.Clamp(cpuPercent, 0.0, 100.0);
}
}
catch
if (wallTimeDelta > 0 && wallTimeDelta < 60000) // Sanity check: < 60 seconds
{
// Ignore any errors in CPU calculation
// CPU percentage divided by cores to match Task Manager (0-100% scale)
var cpuPercent = (cpuTimeDelta / wallTimeDelta / processorCount) * 100.0;
return Math.Clamp(cpuPercent, 0.0, 100.0);
}

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CalculateCpuUsage is invoked from diagnostic status reporting; removing the previous try/catch means failures in Process.Refresh() / TotalProcessorTime (platform/permission/process-lifetime edge cases) can now crash compilation just for diagnostics. Please restore exception shielding (and return 0.0 on failure) so queue reporting can never take down the compiler.

Copilot uses AI. Check for mistakes.
Comment on lines +57 to +81
/// <summary>
/// Search interval tree for a given point, filling a caller-provided list to avoid allocation
/// </summary>
public void Search(int at, List<T> result)
{
SearchSubtree(Root, at, result);
}

/// <summary>
/// Search interval tree for intervals overlapping with given
/// </summary>
/// <param name="interval"></param>
/// <returns></returns>
public List<T> Search(int start, int end)
{
var result = new List<T>();
SearchSubtree(Root, new Interval(start, end), result);
return result;
}

/// <summary>
/// Search interval tree for intervals overlapping with given, filling a caller-provided list to avoid allocation
/// </summary>
public void Search(int start, int end, List<T> result)
{
SearchSubtree(Root, new Interval(start, end), result);
}

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new allocation-free Search(..., List<T> result) overloads append to the provided list without clearing it. That is easy to misuse when callers reuse a list across queries (results accumulate silently). Consider clearing result at the start of these methods (or explicitly documenting that the list is appended-to, not overwritten, and renaming accordingly).

Copilot uses AI. Check for mistakes.
Comment on lines +193 to 227
/// <summary>
/// Fills a caller-provided list to avoid per-call allocation.
/// </summary>
public void Search(int at, List<T> result)
{
FlushDelete();
tree.Search(at, result);

if (delayedAdd && Contains(delayedAddStart, delayedAddEnd, at))
result.Add(delayedAddValue);
}

public List<T> Search(int start, int end)
{
FlushDelete();
FlushAdd();
return tree.Search(start, end);
var result = tree.Search(start, end);

// Append the pending add to the result if it overlaps [start, end], avoiding a tree insertion.
if (delayedAdd && Overlaps(delayedAddStart, delayedAddEnd, start, end))
result.Add(delayedAddValue);

return result;
}

/// <summary>
/// Fills a caller-provided list to avoid per-call allocation.
/// </summary>
public void Search(int start, int end, List<T> result)
{
FlushDelete();
tree.Search(start, end, result);

if (delayedAdd && Overlaps(delayedAddStart, delayedAddEnd, start, end))
result.Add(delayedAddValue);
}

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar to IntervalTree, the allocation-free Search(..., List<T> result) overloads here append into the caller-provided list without clearing it first, which can easily lead to accumulated/stale results when the list is reused. Consider clearing result at method entry (or documenting/renaming to make append semantics explicit).

Copilot uses AI. Check for mistakes.
Comment on lines +236 to +245
public override string ToString()
{
FlushDelete();
FlushAdd();

var enumerator = tree.GetEnumerator();
if (!enumerator.MoveNext())
return string.Empty;
return tree.ToString();
}

Copilot AI Apr 21, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ToString() creates an enumerator to check emptiness but never disposes it. If the underlying enumerator ever holds resources, this could leak; even if it doesn’t today, it’s better to avoid the pattern. Consider using using var enumerator = tree.GetEnumerator(); or checking emptiness via a dedicated property/Count if available.

Copilot uses AI. Check for mistakes.
tgiphil and others added 12 commits April 21, 2026 07:59
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Phil Garcia <phil@thinkedge.com>
Removed a large set of `[MosaUnitTest]` methods (FuzzMethod5068–5099) from Fuzz0050.cs, significantly reducing test coverage for integer/control flow fuzzing. Also added several using directives to MethodScanner.cs; no functional changes in that file.
Cleaned up MethodScanner.cs by removing unnecessary using directives: System.Drawing, System.Reflection, System.Runtime.ConstrainedExecution, and static System.Runtime.InteropServices.JavaScript.JSType. No functional changes were made.
Removed maxWorkers from the "Active" field in the queue status diagnostic message in MethodScheduler.cs. The report now shows only the number of active workers and utilization percentage, simplifying the output.
Insert safepoints by creating new blocks between backedges and loop headers, containing a SafePoint and jump. Track (backedge, header) pairs to avoid duplicates. Move insertion logic to a helper method for clarity and maintainability.
Simplified safepoint insertion by inlining logic and removing the creation of new blocks and branch target replacement. Now uses a HashSet<BasicBlock> to track visited backedges and inserts IR.SafePoint directly after the branch. Updated logging to match the new approach.
Uncommented the ScheduleUnitTests() call in the Initialize() method, ensuring that unit test methods are now scheduled during initialization.
@tgiphil
tgiphil requested a review from Copilot April 25, 2026 01:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 48 changed files in this pull request and generated 6 comments.

Comments suppressed due to low confidence (6)

Source/Mosa.Workspace.Experiment.Debug/Program.cs:1

  • MeasureCompileTime accepts a Stopwatch stopwatch parameter but measures using the static Stopwatch field instead, which makes the parameter ineffective and can produce incorrect timings if a different stopwatch is passed. Use the stopwatch parameter consistently inside the method (or remove the parameter and always use the static field).
    Source/Mosa.Workspace.Experiment.Debug/Program.cs:1
  • MeasureCompileTime accepts a Stopwatch stopwatch parameter but measures using the static Stopwatch field instead, which makes the parameter ineffective and can produce incorrect timings if a different stopwatch is passed. Use the stopwatch parameter consistently inside the method (or remove the parameter and always use the static field).
    Source/Mosa.Workspace.Experiment.Debug/Program.cs:1
  • These settings are assigned multiple times with conflicting values within SetRequiredSettings(), which makes the effective configuration hard to reason about. Consolidate these assignments so each setting is assigned once (or add a short comment explaining why they must be toggled).
    Source/Mosa.Workspace.Experiment.Debug/Program.cs:1
  • These settings are assigned multiple times with conflicting values within SetRequiredSettings(), which makes the effective configuration hard to reason about. Consolidate these assignments so each setting is assigned once (or add a short comment explaining why they must be toggled).
    Source/Mosa.Compiler.Framework/RegisterAllocator/RedBlackTree/DelayedIntervalTree.cs:111
  • The “pending add overlaps” check only tests whether start or end is contained within the pending add, which misses overlap cases like removing a range that fully covers the pending add (e.g., pending add [10,20], remove [0,100]). This contradicts the comment and the newer Overlaps(...) logic used elsewhere; use Overlaps(delayedAddStart, delayedAddEnd, start, end) here for correctness.
	public void Remove(int start, int end)
	{
		// If pending add overlaps, cancel it
		if (delayedAdd && (Contains(delayedAddStart, delayedAddEnd, start) || Contains(delayedAddStart, delayedAddEnd, end)))
		{
			delayedAdd = false;
			return;
		}

Source/Mosa.Utility.Configuration/MOSASettings.cs:1

  • SetDefaultSettings() no longer assigns a default value to MethodScanner. If MosaSettings instances can be reused across runs, this can leave MethodScanner in a stale state from a prior configuration. Reintroduce an explicit default assignment here (or ensure the property is always reset elsewhere before use).

Comment on lines 9 to 12
public static void Register()
{
Registry = new Dictionary<string, BaseArchitecture>();

foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var type in assembly.GetTypes())
{
if (!type.IsAbstract && typeof(BaseArchitecture).IsAssignableFrom(type))
{
var platform = (BaseArchitecture)Activator.CreateInstance(type);
Add(platform);
}
}
}
}

Copilot AI Apr 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PlatformRegistry.Register() previously performed reflection-based discovery and population, but now it only resets the dictionary; this is a breaking semantic change for any consumers relying on auto-discovery. Consider either (a) restoring discovery under a new opt-in method (e.g., RegisterFromLoadedAssemblies()), or (b) renaming this method to reflect its new behavior (e.g., Reset()), and updating call sites accordingly.

Copilot uses AI. Check for mistakes.
}

private T SearchFirstOverlapping(Interval interval)
private bool TrySearchFirstOverlapping(Interval interval, out T value)

Copilot AI Apr 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value = null; will not compile (or will violate nullability expectations) if T is not constrained to a nullable reference type. Prefer value = default; (and, if needed, use nullability annotations) or explicitly constrain IntervalTree<T> with where T : class if null is intended as the “not found” sentinel.

Copilot uses AI. Check for mistakes.
Comment on lines 127 to 131
if (node == Sentinel)
{
throw new KeyNotFoundException("No overlapping interval found.");
value = null;
return false;
}

Copilot AI Apr 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

value = null; will not compile (or will violate nullability expectations) if T is not constrained to a nullable reference type. Prefer value = default; (and, if needed, use nullability annotations) or explicitly constrain IntervalTree<T> with where T : class if null is intended as the “not found” sentinel.

Copilot uses AI. Check for mistakes.
Comment on lines +57 to +63
/// <summary>
/// Search interval tree for a given point, filling a caller-provided list to avoid allocation
/// </summary>
public void Search(int at, List<T> result)
{
SearchSubtree(Root, at, result);
}

Copilot AI Apr 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The XML doc says “filling” a caller-provided list, but the implementation appends without clearing. This is easy to misuse when the same list is reused across calls. Either clear the list inside the method, or update the documentation to explicitly state that results are appended and the caller must clear the list if desired.

Copilot uses AI. Check for mistakes.
Comment on lines 407 to 426
private double CalculateCpuUsage(long currentTicks)
{
try
{
currentProcess.Refresh();
var currentCpuTime = currentProcess.TotalProcessorTime;
var cpuTimeDelta = (currentCpuTime - lastCpuTime).TotalMilliseconds;
currentProcess.Refresh();
var currentCpuTime = currentProcess.TotalProcessorTime;
var cpuTimeDelta = (currentCpuTime - lastCpuTime).TotalMilliseconds;

var ticksDelta = currentTicks - lastCpuCheckTicks;
var wallTimeDelta = (ticksDelta / (double)Stopwatch.Frequency) * 1000.0; // Convert to milliseconds
var ticksDelta = currentTicks - lastCpuCheckTicks;
var wallTimeDelta = (ticksDelta / (double)Stopwatch.Frequency) * 1000.0; // Convert to milliseconds

lastCpuTime = currentCpuTime;
lastCpuCheckTicks = currentTicks;
lastCpuTime = currentCpuTime;
lastCpuCheckTicks = currentTicks;

if (wallTimeDelta > 0 && wallTimeDelta < 60000) // Sanity check: < 60 seconds
{
// CPU percentage divided by cores to match Task Manager (0-100% scale)
var cpuPercent = (cpuTimeDelta / wallTimeDelta / processorCount) * 100.0;
return Math.Clamp(cpuPercent, 0.0, 100.0);
}
}
catch
if (wallTimeDelta > 0 && wallTimeDelta < 60000) // Sanity check: < 60 seconds
{
// Ignore any errors in CPU calculation
// CPU percentage divided by cores to match Task Manager (0-100% scale)
var cpuPercent = (cpuTimeDelta / wallTimeDelta / processorCount) * 100.0;
return Math.Clamp(cpuPercent, 0.0, 100.0);
}

return 0.0;

Copilot AI Apr 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous implementation guarded CPU usage calculation with a try/catch, but that protection is removed. If Process.Refresh()/TotalProcessorTime throws (platform/permission/process-state issues), it can now propagate and disrupt scheduling/diagnostics. Consider restoring exception handling around this diagnostic-only code path (ideally narrowly scoped to expected exception types).

Copilot uses AI. Check for mistakes.
Comment on lines +136 to +140
public void Schedule(List<MosaMethod> methods)
{
Setup();
Compiler.MethodScheduler.Schedule(methods);
}

Copilot AI Apr 25, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This overload calls Setup() while Schedule(MosaMethod method) does not, creating inconsistent behavior and potential redundant work (especially since Compile() also calls Setup()). Align the overloads by either requiring callers to call Setup() explicitly for both, or making both overloads internally ensure setup in the same way (and ensuring Setup() is guaranteed idempotent).

Copilot uses AI. Check for mistakes.
@tgiphil
tgiphil merged commit 10c1cce into mosa:master Apr 25, 2026
71 checks passed
@tgiphil
tgiphil deleted the 604-allocator branch May 10, 2026 22:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Development

Successfully merging this pull request may close these issues.

2 participants