Open esoterra opened 9 months ago
Thanks for filing this idea and definitely the use case (call-scoped bump-allocation) makes sense.
In the Preview 2 timeframe, indeed you can approximate this feature by just using the realloc
hook to lazily (on first call) mark the bump allocator and the post-return
hook to reset to that mark (at the modest cost of one branch per realloc
call), taking advantage of the component invariants which disallow reentrancy.
With native async in a Preview 3 timeframe where you can have multiple concurrent export calls in flight, indeed that does rules out this simple strategy, but it seems like a pre-call
hook isn't quite enough -- you also need some sort of per-export-invocation "task-id" that is explicitly threaded through all the realloc
and final post-return
calls. For this and other reasons, I've been assuming that we'll need an ambiently-available/-supplied "task-index". Once we have that, then the same "lazy mark" strategy that works in Preview 2 could be applied in Preview 3 (making the lazy marking per-task instead of globally). But separately, I've realized that an asynchronously-callable export needs to be able to express backpressure before the call starts (b/c even just starting the call can consume non-trivial memory (e.g., for list
s)), which suggests some async pre-call-like hook (for expressing backpressure), so perhaps we end up getting effectively what you're asking for as a matter of course in Preview 3.
I think this has value in itself by simplifying the lifecycle management of allocators and other per-call resources for compiler codegen, but I agree that it really becomes important in Preview 3 as part of a fully-conceived task-id-based concurrent call lifecycle tracking enhancement to the canonical ABI.
The
post-return
canonopt provides a way for components to clean up allocated result values after the caller has read them.It would also be valuable to provide components a way to set things up before the arguments are allocated and copied in. This could be achieved by adding another canonopt (named e.g.
pre-param
,pre-call
,pre-alloc
) which allows Components to specify a core function that is called at the beginning of a Component function call before parameters are allocated.As a specific use case, toolchains may want to use a bump allocator whose lifecycle is tied to a single Component function call for function parameters, internal data, and return values. Using this new canonopt, it would be trivial to set it up before params are allocated and tear it down using
post-return
after return values have been consumed.You can implement this currently by creating a bump allocator at startup time and then resetting it at
post-return
but I believe that when concurrency using async (and potentially threads/shared?) comes in and multiple calls (and as a result multiple bump allocators) are alive at the same time this simple pattern will no longer work.