mirror of
https://github.com/nim-lang/Nim.git
synced 2026-09-04 21:00:31 +00:00
IC: a backend stage stops building the interface half it cannot read
`populateInterfaceTablesFromIndex` stubbed a `PSym` for every global symbol a
module declares and inserted it into `interf` and/or `interfHidden`. On a
68-module target that is 2.37M stubs across the build — and 2.04M of them go
into `interfHidden` alone, which a `cg`/`emit` stage has no way to reach.
`interfHidden` is selected exclusively by `modulegraphs.interfSelect`, and only
when `optImportHidden` is in the module's options. That flag is set in exactly
one place — `importer.importModuleAs`, i.e. during sem. A backend stage builds
its module symbols in `moduleFromNifFile` and never imports anything, so the
flag cannot be set and the table cannot be selected. Skipping the hidden-only
branch there is unobservable, not merely unlikely to be observed.
Exported symbols still go into both tables. That is 0.33M inserts against the
2.0M saved, and it leaves `interfHidden` a coherent view — a module with no
hidden symbols — rather than an empty one, should anything ever consult it.
interface tables 1401ms -> 863ms
loadDepClosure 2771ms -> 2309ms
cold --ic:on build 9.38s -> 8.91s
Skipping the tables WHOLESALE in a backend stage does not work, and the failure
is worth recording since it is the obvious next thought: the exported half is
what `magicsys.getSysSym` resolves through, so the stage dies with "system
module needs: pointer". Skipping them in the FRONTEND is worse still — `nim m`
loses `defined`.
Verified: both configurations build; `tests/ic` 40/40; 67/67 generated `.c`
byte-identical, cursor still identical to `PNode`.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FMyRHByv7hhaQJ4Pa1bHbE
This commit is contained in:
@@ -3688,13 +3688,32 @@ proc populateInterfaceTablesFromIndex(c: var DecodeContext; module: FileIndex;
|
||||
var indexTab = move c.mods[module].index
|
||||
|
||||
# Add all symbols to interf (exported interface) and interfHidden
|
||||
# A BACKEND stage cannot read the hidden-only half, so it does not build it.
|
||||
# `interfHidden` is reached exclusively through `modulegraphs.interfSelect`,
|
||||
# which picks it only when `optImportHidden` is in the module's options — and
|
||||
# that flag is set in exactly one place, `importer.importModuleAs`, i.e.
|
||||
# during sem. `cg`/`emit` build their module symbols in `moduleFromNifFile`
|
||||
# and never import anything, so the flag cannot be set and the table cannot be
|
||||
# selected. The saving is the bulk of this proc: on a 68-module target the
|
||||
# hidden branch stubs 2.0M symbols against the exported branch's 0.33M.
|
||||
#
|
||||
# Exported symbols are still added to BOTH tables. That costs little beside
|
||||
# the above and leaves `interfHidden` a coherent view (a module with no hidden
|
||||
# symbols) rather than an empty one, should anything ever consult it.
|
||||
let conf = c.infos.config
|
||||
let backendStage = conf.cmd == cmdNifC and
|
||||
(conf.icBackendStage == "cg" or conf.icBackendStage == "emit")
|
||||
|
||||
prof pIfaceModules
|
||||
for nifName, entry in indexTab:
|
||||
if entry.vis == Exported:
|
||||
prof pIfaceExported
|
||||
let sym = loadSymFromIndexEntry(c, module, nifName, entry, thisModule)
|
||||
if sym != nil:
|
||||
strTableAdd(interf, sym)
|
||||
strTableAdd(interfHidden, sym)
|
||||
elif not nifName.startsWith("`t"):
|
||||
elif not backendStage and not nifName.startsWith("`t"):
|
||||
prof pIfaceHidden
|
||||
# do not load types, they are not part of an interface but an implementation detail!
|
||||
#echo "LOADING SYM ", nifName, " ", entry.offset
|
||||
let sym = loadSymFromIndexEntry(c, module, nifName, entry, thisModule)
|
||||
|
||||
@@ -31,7 +31,7 @@ when defined(icBNodeProf):
|
||||
ProfSlot* = enum
|
||||
pKind, pTagKindHit, pTagKindMiss, pAstChildren, pSkip, pSon, pLen,
|
||||
pLastSon, pIterYield, pSym, pTyp, pTypTagLit, pOrigin, pNilType,
|
||||
pGenBodyCalls, pInfo
|
||||
pGenBodyCalls, pInfo, pIfaceExported, pIfaceHidden, pIfaceModules
|
||||
TimeSlot* = enum
|
||||
tLoadClosure, tModuleId, tBifLoad, tPosIndex, tTopLevel, tInterfTables,
|
||||
tTransform, tHandOff, tGenBody, tAnalyses,
|
||||
|
||||
Reference in New Issue
Block a user