compiler: isolate per-invocation frontend state - #2221
Conversation
There was a problem hiding this comment.
Review: isolate per-build frontend and SSA state
Solid, well-tested refactor. The isolation goal is achieved: every active symbol-generation path in ssa/ and cl/ is migrated to the Program/Namer-scoped naming methods, the def/use pair for method-capability keys (ssa/globaldce.go and ssa/interface.go) both use the scoped PathOf so RewriteMainPrefix cannot silently break DCE, and the concurrent-build story (sync.Once init + frontendDebugMu gating the process-global SetDebug switches) is coherent. Performance is neutral — Program/Builder are pointer aliases and Namer is a one-bool value, so the new method values/closures don't allocate on hot paths. No security regressions; binding LLVM tools to explicit paths instead of mutating the process PATH is a modest improvement.
A few concrete items below. Inline comments carry the diff-line findings; the rest are here.
Findings not tied to a diff line
-
ssa/type.go:593— unscopedNameOfstraggler.namedTypeEquivalentstill calls the package-levelNameOf(zero-valueNamer,RewriteMainPrefix=false) while its siblingllvmNameOf(ssa/type.go:524) was migrated top.NameOf. It's self-consistent today (both operands share the unscoped namer), but mixing scoped and unscoped naming in adjacent equivalence code is a maintenance hazard: ifmain-package named types are compared here underRewriteMainPrefix, the equivalence result could diverge from the scoped symbol used at line 524. Consider threading theProgramand usingp.NameOfin both comparisons. -
cl/compile.go— legacy constructors not marked deprecated.EnableDebug/EnableDbgSyms/EnableTrace/EnableExportRenamegained// Deprecated:notes, butNewPackage/NewPackageEx/NewPackageExWithEmbed/NewPackageExWithEmbedMetawere not, even though they funnel throughlegacyOptions()and thus stay unisolated (re-reading process globals +LLGO_SHADOW_STACK). A matching// Deprecated: use NewPackageExWithEmbedMetaOptionsnote would make the isolation contract discoverable across the whole public surface. -
New exported
Programnaming methods lack doc comments (ssa/type.go:NameOf,FullName,PathOf,FuncName,TypeArgs). These are the primary replacement API for the removed process-global path, yet the package-level free functions directly above each are documented and these are not. A one-line comment noting each applies the Program'sRewriteMainPrefixpolicy (vs. the package-level function's zero-value namer) would help. Theabi.Namerexported methods are likewise undocumented. -
xtool/env/llvm/llvm.gotool-bin doc comments forClangBin/ClangXXBin/LLVMArBin/LLCBinsay "returns the<tool>executable from this LLVM installation," but whenbinDir == ""they return the bare command name for PATH resolution (asBinDir's own comment documents, and asTestToolBinsFallBackToPATHNamesasserts). MirrorBinDir's wording about the PATH fallback. -
internal/build/request.gowithEnvsilently drops malformed (non-KEY=VALUE) entries from the passthrough environment, a behavior change from the priorappend(slices.Clone(os.Environ()), ...). It only feedsgo list's env (which rejects such entries anyway), so it's harmless — but the doc comment mentions dropping malformed entries only when replacing, not from the passthrough; worth a word.
| args = append(args, pkg.PkgPath) | ||
|
|
||
| cmd := exec.Command("go", args...) | ||
| ctx.configureCommand(cmd) |
There was a problem hiding this comment.
ctx.configureCommand(cmd) here is dead: it sets cmd.Dir and cmd.Env, but line 415 overwrites cmd.Dir (from ctx.conf.Dir) and lines 421-424 overwrite cmd.Env unconditionally. So this call has no effect.
More notably, this go list invocation ends up using os.Environ() (the live process environment) rather than the build's captured ctx.environ snapshot that the rest of this PR deliberately threads through exec commands. A concurrent build that mutated the process env would leak in here. Either drop the redundant configureCommand call and add a note that this command intentionally uses live env + conf.Dir, or build on top of the ctx.environ snapshot for consistency with the other commands.
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
82f3bf3 to
2e73083
Compare
2e73083 to
05b1efd
Compare
LLGo baseline benchmarks
Program measurements
Core language and compiler benchmarks
No main baseline exists yet; all metrics are marked Warning
|
e018a21 to
ef96705
Compare
|
Reworked on top of #2246 ( The old SSA naming layer is gone: no I also addressed the remaining applicable review item by marking the legacy Validated locally:
|
ef96705 to
8c82142
Compare
|
CI follow-up at
|
8c82142 to
f60aa0c
Compare
Summary
cl.OptionsDependency and review boundary
Based on current
main, which includes #2246 and its unconditional main-package symbol prefix.The intended review diff is:
8aa41210(compiler: always use main symbol prefix #2246 head)c46521e4Please review only
8aa41210..c46521e4.Simplification from the previous version
abi.Namerand Program-owned naming policyRewriteMainPrefixstate and its dual-policy concurrency testsCompatibility boundary
NewPackageExWithEmbedMetaOptionswith explicitcl.Optionscl.SetDebugorssa.SetDebug; compiler-verbose emits a package-level compile marker without process-wide stateTests
GOCACHE=/private/tmp/llgo-2221-gocache go test ./internal/build ./cl ./ssa -count=1GOCACHE=/private/tmp/llgo-2221-gocache go test -race ./internal/build -run '^TestConcurrentInvocationsIsolateFrontendOptions$' -count=1GOCACHE=/private/tmp/llgo-2221-gocache go test ./cl -run '^TestFrontendOptions$' -count=1legacyOptionsandfrontendOptionsboth 100%; concurrent verbose/non-verbose invocation paths executed without a frontend lockgit diff --check