mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-25 20:28:48 +08:00
[Loader] Collect stub-eligible NIDs in one pass over descriptors (#489)
BuildImportStubs filtered orderedImportNids by calling ShouldCreateImportStub for each unique NID, and every call scanned the entire descriptor list looking for a match. On a real module both the NID count and the descriptor count run into the thousands, so the filter degraded to O(nids * descriptors) ordinal string comparisons on the one-time load path. Replace the per-NID rescan with a single pass over the descriptors that builds a HashSet of eligible NIDs, then filter orderedImportNids with O(1) membership. Eligibility is unchanged: a NID qualifies when any of its descriptors is non-weak, or is weak but resolvable via the module manager. ShouldCreateImportStub is retained (still used by the DEBUG self-checks), and a self-check now asserts the set-based collector agrees with the per-NID rule. Co-authored-by: slick-daddy <slick-daddy@users.noreply.github.com>
This commit is contained in:
@@ -714,8 +714,9 @@ public sealed class SelfLoader : ISelfLoader
|
|||||||
|
|
||||||
importedRelocations = BuildImportedRelocations(descriptors);
|
importedRelocations = BuildImportedRelocations(descriptors);
|
||||||
|
|
||||||
|
var stubEligibleNids = CollectStubEligibleNids(descriptors, moduleManager);
|
||||||
var stubImportNids = orderedImportNids
|
var stubImportNids = orderedImportNids
|
||||||
.Where(nid => ShouldCreateImportStub(nid, descriptors, moduleManager))
|
.Where(stubEligibleNids.Contains)
|
||||||
.ToArray();
|
.ToArray();
|
||||||
var stubsByAddress = CreateImportStubMapping(virtualMemory, stubImportNids);
|
var stubsByAddress = CreateImportStubMapping(virtualMemory, stubImportNids);
|
||||||
Console.WriteLine($"[LOADER] Created {stubsByAddress.Count} import stubs");
|
Console.WriteLine($"[LOADER] Created {stubsByAddress.Count} import stubs");
|
||||||
@@ -1160,6 +1161,35 @@ public sealed class SelfLoader : ISelfLoader
|
|||||||
isWeak);
|
isWeak);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Collects every NID that needs a trap import stub in a single pass over the
|
||||||
|
// descriptors. This mirrors ShouldCreateImportStub applied per NID, but avoids
|
||||||
|
// the O(nids * descriptors) rescan that filtering each unique NID against the
|
||||||
|
// full descriptor list would incur on large modules. A NID qualifies as soon as
|
||||||
|
// one of its descriptors is non-weak, or is weak but resolvable via the module
|
||||||
|
// manager.
|
||||||
|
private static HashSet<string> CollectStubEligibleNids(
|
||||||
|
IReadOnlyList<RelocationDescriptor> descriptors,
|
||||||
|
IModuleManager? moduleManager)
|
||||||
|
{
|
||||||
|
var eligible = new HashSet<string>(StringComparer.Ordinal);
|
||||||
|
for (var i = 0; i < descriptors.Count; i++)
|
||||||
|
{
|
||||||
|
var descriptor = descriptors[i];
|
||||||
|
var nid = descriptor.ImportNid;
|
||||||
|
if (nid is null || eligible.Contains(nid))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!descriptor.IsWeak || moduleManager?.TryGetExport(nid, out _) == true)
|
||||||
|
{
|
||||||
|
eligible.Add(nid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return eligible;
|
||||||
|
}
|
||||||
|
|
||||||
private static bool ShouldCreateImportStub(
|
private static bool ShouldCreateImportStub(
|
||||||
string nid,
|
string nid,
|
||||||
IReadOnlyList<RelocationDescriptor> descriptors,
|
IReadOnlyList<RelocationDescriptor> descriptors,
|
||||||
@@ -2431,6 +2461,19 @@ public sealed class SelfLoader : ISelfLoader
|
|||||||
Debug.Assert(
|
Debug.Assert(
|
||||||
!ShouldCreateImportStub("weak", [weak], moduleManager: null),
|
!ShouldCreateImportStub("weak", [weak], moduleManager: null),
|
||||||
"An unresolved weak symbol incorrectly received a trap import stub.");
|
"An unresolved weak symbol incorrectly received a trap import stub.");
|
||||||
|
|
||||||
|
var strong = new RelocationDescriptor(
|
||||||
|
TargetAddress: 0x3000,
|
||||||
|
Addend: 0,
|
||||||
|
ImportNid: "strong",
|
||||||
|
SymbolValue: 0,
|
||||||
|
RelocationValueKind.Pointer,
|
||||||
|
IsDataImport: false);
|
||||||
|
var mixed = new List<RelocationDescriptor> { weak, strong };
|
||||||
|
var eligible = CollectStubEligibleNids(mixed, moduleManager: null);
|
||||||
|
Debug.Assert(
|
||||||
|
eligible.Contains("strong") && !eligible.Contains("weak"),
|
||||||
|
"CollectStubEligibleNids disagreed with the per-NID stub eligibility rule.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ulong AlignUp(ulong value, ulong alignment)
|
private static ulong AlignUp(ulong value, ulong alignment)
|
||||||
|
|||||||
Reference in New Issue
Block a user