perf: replay LCNF declaration extensions without per-declaration bookkeeping

This PR removes the per-declaration overhead #15232 introduced in the LCNF declaration extensions, which cost about 1% of instructions when compiling modules with many declarations, while keeping the linear-time replay of realized constants.

#15232 tracked the insertion order of the `baseExt`, `monoExt`, `impureExt` and `impureSigExt` states in a list so that a replay only visits the declarations a realization added. Maintaining that list costs a lookup and an allocation for every saved declaration, twice because these extensions are synchronous, and this is paid by every module whether or not it realizes anything. The extension state is now a plain `PHashMap` again, and the replay uses the new `PersistentHashMap.foldlNewEntries`, which folds over the entries of one map whose keys are not in another. Its implementation skips the nodes and entries the two maps share physically, so when the new map was obtained from the old one by insertions the cost is proportional to the number of insertions, and it agrees with the reference implementation on every input.

Instruction counts compiling `Lean.Parser.Command` are 11.34 G on master, 11.45 G with #15232, and 11.33 G with this change; `Init.Data.List.Basic`, which performs 147 realizations, goes from 11.65 G on master to 11.62 G. The `realizations` benchmark is unchanged at about 3x faster than master.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2 files changed