Mostly echoing @mdroettboom’s excellent answers:
LLVM is used at build time to compile individual micro-op instructions into mostly-opaque blobs of machine code. These blobs are dumped into a header file, which is used to build CPython itself.
At runtime, we compile a sequence of micro-ops by “simply” copying the machine code for each one, almost verbatim. So instead of firing up LLVM, it’s “just” a memcpy
and a couple of loops to fix up parts of the code. Implementation here, in C.
The PEP could probably be updated to make the run-time/build-time distinction clearer.
I’m not aware of any patents on the approaches used here.
No, when their refcount hits zero, and no.
…at least, that’s the state right now. The current memory allocation/freeing scheme can be summed up as “I got it working a while back and haven’t touched it since”. All of the points you make above are things I want to do, but simply haven’t had the time to work on yet.
One main thing to keep in mind is that I’d like to avoid introducing any “official” JIT APIs (or encouraging users to tweak them) while it’s still experimental. I could definitely see tunable controls for enabling/disabling the JIT, controlling max memory, and more control over GC of cold traces in the future, though, exposed through the sys
module, environment variables, etc.
The good news is that all of the things you ask for should be easy to do. We already maintain a doubly-linked list of all JIT code (for unrelated correctness reasons) and have ways to turn the JIT on and off at runtime (for testing).
Yep, and it always will be (even on platforms where LLVM is available).