implement "engine" for managing inference/codegen (#54816)
Continuing from previous PRs to making CodeInstance the primary means of
tracking compilation, this introduces an "engine" which keeps track
externally of whether a particular inference result is in progress and
where. At present, this handles unexpected cycles by permitting both
threads to work on it. This is likely to be optimal most of the time
currently, until we have the ability to do work-stealing of the results.
To assist with that, CodeInstance is now primarily allocated by
`jl_engine_reserve`, which also tracks that this is being currently
inferred. This creates a sort of per-(MI,owner) tuple lock mechanism,
which can be used with the double-check pattern to see if inference was
completed while waiting on that. The `world` value is not included since
that is inferred later, so there is a possibility that a thread waits
only to discover that the result was already invalid before it could use
it (though this should be unlikely).
The process then can notify when it has finished and wants to release
the reservation lock on that identity pair. When doing so, it may also
provide source code, allowing the process to potentially begin a
threadpool to compile that result while the main thread continues with
the job of inference.
Includes fix for #53434, by ensuring SOURCE_MODE_ABI results in the item
going into the global cache.
Fixes #53433, as inInference is computed by the engine and protected by
a lock, which also fixes #53680.