We would like to make Parser construction as speedy as possible. Calling the ParserFirstCallInit hook to register every single parser function and extension tag on every single parser object instantiation (as is now done) is a waste: 99.9% percent of extension and parser functions are available in every constructed parser, so we keep building the same maps and tables of tags and functions again and again.
Instead, extension and parser function registration should be via the standard ExtensionRegistry, and the hook/tag extension API should give extensions/parser functions the ability to 'nope out' of expansion if the tag/function is supposed to be disabled in that parser context. (This latter functionality will rarely be the right thing to do, since it's going to end up splatting the tag/function text literally on the page, but it might be necessary for, say, security or access control reasons.)
Note that this doesn't directly give you the ability to, say, have multiple extensions implement the <foo> tag, with one or the other registered during parser construction time. That's fine: just create a single shared <foo> implementation which calls a hook to dispatch to one or the other implementation dynamically. (Or just Don't Do That.) We might optionally change the extension mechanism to allow multi-maps from extension/tag name to implementation to allow fallback, but this seems like unnecessary complexity at this time.
See also T250444: Deprecate and remove Parser::firstCallInit(), which is about removing the Parser::firstCallInit method. This is about removing the hook.