Add ABIAdapter / DispatchTrampoline and use for @ccallable / @cfunction#62245
Draft
topolarity wants to merge 5 commits into
Draft
Add ABIAdapter / DispatchTrampoline and use for @ccallable / @cfunction#62245topolarity wants to merge 5 commits into
ABIAdapter / DispatchTrampoline and use for @ccallable / @cfunction#62245topolarity wants to merge 5 commits into
Conversation
df9a3ef to
ccac454
Compare
f736388 to
7f4b875
Compare
Add shared machinery for caches that key a TypeMap exactly on a signature type and hold several records per entry: an intrusive, append-only list chained through an atomic next field embedded in each record, walked lock-free and mutated under the owning cache's writelock. Keys stay packed inline in the records; a match callback reads them directly. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Introduce the ABIAdapter datatype and a process-global adapter cache (`Core.abi_adapters`, an ABIAdapterCache with its own writelock), interning one JIT'd ABI-adapter thunk per distinct (sigt, rt, ci, specsig, is_opaque_closure, nargs) rather than one per call site. Adapters serialize as first-class image code: records are fvar-wired (jl_get_adapter_id), reset their bucket `next`, and are re-interned on load (jl_reintern_abi_adapter). Because an adapter has no compiled-code edge of its own, it is reported to the serializer via `ext_foreign_code` (renamed from ext_foreign_cis) so independent adapters -- ones not owned by any trampoline -- are rooted through the pre-dump GC and serialized/reinterned in both incremental and full/AOT images. The codegen-free fallback (jl_jit_abi_converter_fallback) is cache-aware. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add the DispatchTrampoline datatype and a process-global trampoline cache
(`Core.dispatch_trampolines`, a DispatchTrampolineCache with its own writelock),
interning one @cfunction/@ccallable dispatch record per (sigt, rt). A trampoline
holds `last_invoked` -- a Union{CodeInstance, ABIAdapter} recording its resolved
target -- plus a redundant `fptr` cache for the hot-path poll.
Trampolines serialize alongside their adapters: the record's bucket `next` is
reset and it is re-interned on load (jl_reintern_trampoline); `last_invoked`
serializes as a normal reference so the first post-load call restores `fptr`
straight from it. The resolver itself (jl_resolve_trampoline) lands with the
@cfunction migration.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… delete cfuncdata
Reroute @cfunction/@ccallable off the per-call-site cfuncdata global onto the
interned DispatchTrampoline + ABIAdapter caches. emit_abi_call now embeds the
interned trampoline and polls last_world/fptr, falling back to the runtime
resolver jl_resolve_trampoline (which restores fptr from the trampoline's
last_invoked, JITing/interning an ABIAdapter only when needed). The AOT path
(generate_cfunc_thunks/emit_trampoline_adapter) materializes each trampoline's
adapter record and, outside --trim, eagerly enqueues the dynamic-dispatch
("unspecialized") adapter so a codegen-free interpreter run of a non-trimmed
image can still dispatch. The obsolete cfuncdata_t struct and jl_get_abi_converter
are removed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Add a JULIA_LOAD_CODEGEN_LIB environment variable (0/no) that makes the loader skip libjulia-codegen and install the codegen-stubs fallbacks, exactly as when the library is absent -- so the no-codegen configuration can be tested and debugged without hiding the library file. Use it to extend the cfunction adapter serialization test with a codegen-free child process: every @cfunction call must be served by the ABI adapters serialized into the package image, and after a method redefinition the resolver must dispatch through the image-serialized dynamic-dispatch adapter rather than error. A jl_get_LLVM_VERSION probe (0 from the fallback stub) guards against the test passing vacuously through the JIT. Fixes JuliaLang#61949 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
7f4b875 to
15f39e0
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This introduces first-class types for the adapters / trampolines we already generate for
@cfunction/@ccallable:emit_abi_converter, et al)cfuncdata_t)which allows them to be cached and serialized independently.
The adapter / trampoline split is designed to support:
OpaqueClosure: adapter only@cfunction: trampoline + adapter (sometimes)TypedCallable: trampoline + adapter (always) + runtime cacheSince TypedCallable does not have the top-level eval / type-restrictions that
@cfunctionhas where the ABI is fixed at lowering time, the runtime cache implemented here is required so that we can provide ABI adapters forTypedCallableconstruction in type-unstable / interpreted code while leaving JIT work bounded (under type-stability assumptions). It also allows us to re-use ABI adapters / trampolines across multiple@cfunctionsites, altough that's a fairly marginal benefit.TODO: Explain the cache design / trade-offs + serialization strategy +
unspecializedhandling (#61949)Co-developed by Claude Opus 4.8 🤖
(draft until I sweep the latest re-factor and clean up the AI-isms + needs a full review for bugs / logic problems)