[super! 3/6] Invoke through an erased context instead of the proxy type - #68
Open
mingxwa wants to merge 1 commit into
Open
[super! 3/6] Invoke through an erased context instead of the proxy type#68mingxwa wants to merge 1 commit into
mingxwa wants to merge 1 commit into
Conversation
An invoker's erased function pointer was typed R (*)(proxy<F>&, D, Args...), so its type named the facade it was built for. That is fine while metadata is only ever read by a proxy of exactly that facade, but it prevents one proxy from reusing another's invoker: two proxy types have different layouts, so passing one where the other is expected is not valid. Introduce erased_context, which carries only a pointer to the storage of the contained value, and type invokers as invoker<Ctx, O>. Invocation now resolves the contained type inside the context rather than through reinterpret_invoke, and the lifetime dispatches take a void* rather than a target proxy, so their invokers no longer mention F either. Resetting the source metadata after an rvalue-qualified call moves to the call site, where the facade is known. Declare ptr_ ahead of meta_ so that the storage of the contained value lies at offset 0. Every invocation now builds a context from it, and at offset 0 that context is the address of the proxy itself. Where a proxy is invoked more than once, the caller then keeps a single value live instead of a separate context pointer: on aarch64 that removes a spill and reload of the context across the first call, and shrinks the frame by 16 bytes. Neither sizeof(proxy) nor its alignment changes. relocate_dispatch becomes a tag with its own erased_context specialization, which absorbs the bitwise-relocation path that used to be selected via internal_dispatch, and internal_dispatch is removed. substitution_dispatch needs the same path, because it relocates a bitwise-relocatable value without requiring it to be move-constructible, so it gets a specialization too; both it and the specialization drop out once `super` replaces substitution. Removes the public reinterpret_invoke, which had no remaining use: the invoker macro was its only caller inside the library.
mingxwa
force-pushed
the
user/mingxwa/super-stage3
branch
from
August 15, 2026 10:27
685a990 to
1335a47
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.
An
invoker's erased function pointer was typedR (*)(proxy<F>&, D, Args...), so its type named thefacadeit was built for. That is fine while metadata is only ever read by aproxyof exactly thatfacade, but it prevents oneproxyfrom reusing another'sinvoker: twoproxytypes have different layouts, so passing one where the other is expected is not valid. Reusing a basefacade's invokers is what super (more PRs coming ahead) needs.erased_context, which carries only a pointer to the storage of the contained value. Invokers becomeinvoker<Ctx, O>.void*rather than a targetproxy, so their invokers no longer mentionFeither.relocate_dispatchbecomes a tag with its ownerased_contextspecialization, which absorbs the bitwise-relocation path that used to be selected throughinternal_dispatch.internal_dispatchis removed.ptr_is declared ahead ofmeta_so that the storage of the contained value lies at offset0. Every invocation now builds a context from it, and at offset0that context is the address of theproxyitself.Declaring
ptr_first is what keeps the new indirection free at the call site. Where aproxyis invoked more than once, the caller keeps a single value live instead of a separate context pointer. On aarch64 that removes a spill and reload of the context across the first call and shrinks the frame by 16 bytes:substitution_dispatchneeds the same relocation path, because it relocates a bitwise-relocatable value without requiring it to be move-constructible, so it gets a specialization too. That specialization will be removed together withsubstitution_dispatchin the last PR of this stack.Breaking change. Removes the public
reinterpret_invoke.