component-model icon indicating copy to clipboard operation
component-model copied to clipboard

Component Model should allow `post-return`s to take no result-specific params

Open esoterra opened this issue 1 year ago • 4 comments

In components where the post return function doesn't need to know which values being returned because (e.g. the entire bump allocator is reset) the current requirement that the type of post-return takes as parameters the return values is very inconvenient.

It would be very helpful if it was possible to provide a function taking no result-based arguments either as a separate canonical option or as post-return being detected as behaving this way by their type.

For a concrete example, in the Claw compiler, a prebuilt allocator module is used which exports a clear function. This clear function cannot be used in a post-return for a function which returns anything because it's type is not correct.

As a result, in order to create valid post-returns

  • the code module needs to import clear
  • new post-return functions are needed in the code module
    • that need potentially new types to be encoded
    • that ignore their arguments
    • that all call clear in the exact same way
  • those exported functions need to be aliased,
  • and then each generated post-return may be used as post-return

This is a ton of work and unneeded binary size for something the Component Model could make unnecessary.

esoterra avatar Feb 23 '24 22:02 esoterra

As another example, Components which internally book keep their returns and don't need to be told what the results were will also need to generate wrappers they do not really need.

esoterra avatar Feb 23 '24 22:02 esoterra

For what it is worth, ComponentizeJS does the same thing here - https://github.com/bytecodealliance/ComponentizeJS/blob/main/crates/spidermonkey-embedding-splicer/src/splice.rs#L679, by synthesizing the post-return functions as necessary to wrap the global bump deallocator.

I don't find the overhead too bad there, so don't have a major preference with regards to this, but it's another case of the same thing for sure.

guybedford avatar Feb 25 '24 00:02 guybedford

The use case makes sense, but as always, it's a tradeoff with adding more cases and complexity to the spec/runtime vs. some overhead. In general, we accept that the CABI won't be a perfect fit for everyone and will incur some overhead (code size or perf), so to motivate the extension, we'd want the code-size burden to be a non-negligible % of a real component's overall binary size (which I'd be rather surprised to hear if it was).

Incidentally though, the call.start/call.return built-ins motivated by Preview 3 async I was realizing could actually work just fine (w/o requiring stack-switching) in a sync context and provide meaningful expressivity benefits. In particular, once you can return values with call.return, you don't need post-return. (Symmetrically, call.start would subsume a "pre-call" hook that lets you execute code before the arguments are copied in.) So then perhaps the new canonopt is to opt into using call.start/call.return in sync contexts, which ends up covering this use case.

lukewagner avatar Feb 26 '24 17:02 lukewagner

I like that idea! To your point it could solve both this and #289 in a way that should be fairly easy to emit code for.

It also means that if your cleanup logic is optimized to be a no-op, you don't still have an empty core function, corresponding alias, and corresponding post-return canon opt sitting around.

esoterra avatar Feb 26 '24 17:02 esoterra