-
Notifications
You must be signed in to change notification settings - Fork 301
witx tool can document how to polyfill some interfaces #164
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
When implementing the polyfill in Wasmer I ran into an issue which seem fundamentally unsolvable: when sizes of caller-allocated objects shrink from version n to n+1, it requires the polyfill to do extra memory allocation, or to do "clever" things like saving the state of the current memory, acting like the memory off the end of the allocation is its own, executing the new call, saving the resulting memory, rewriting the old memory, and then rewriting the new memory within the bounds of the existing allocation. The hack also breaks if the host-call accesses memory which is now aliased by the "extended" struct. In both of these cases WASI programs that worked before can fail: due to either no memory left to allocate or accessing beyond the end of the allocation which causes memory to be out of bounds or aliased in a bad way. I found the first way difficult due to not having a way to allocate Wasm memory safely from the host. If such a thing exists for WASI, I'm not aware of it. Perhaps this is an acceptable tradeoff, but I wish there was a cleaner way to do this |
|
I am aiming to make polyfilling in wasi-common work without ever manipulating Wasm memory like you describe, and do all conversions in regular host code. However, I haven't actually gotten to that point yet, so I'm not yet sure if it is going to work. I do not know of any mechanism to safely interact with a guest memory allocator from the host. We could possibly come up with one that works for one particular guest language ABI, but a portable cross-language solution would be quite difficult. Thanks for sharing your experience with this! I'll report back with how things turn out. |
|
Current ideas on this work:
|
|
This code can now emit a markdown doc describing polyfill requirements between snapshot 1 and 0, see below. The The more interesting polyfill to document is the mapping between ephemeral and snapshot 1, now that modularization has landed. To do so, this tool needs to understand function name mappings. Providing all of the mappings as command line arguments would be very long, and the wrong place to specify this sort of important information. So, I'm going to create a .witxpolyfill document parser so that we can describe these name mappings as s-expressions. |
|
Nice! That sounds good! Having these migrations automated is huge |
|
Just to be clear this tool shows you where there is incompatibility in ABI in terms of the argument and structures passed across the boundary? Since we don't encode any semantics I assume it can't tell you when the semantics differ? |
|
Right, this tool makes no attempt to reason about semantics. Its strictly about the ABI. We haven't gone and made any major semantic changes yet (that I'm aware of) but when we do, perhaps the name mapping language will have a way to indicate that, although a pair of functions may appear to be ABI compatible, they are not semantically compatible. We can cross that bridge when we come to it. |
|
I think this is at a reasonable point where we can merge it, and come up with a way to describe more complex mappings as a follow-on PR. I'd also be happy to pass that task to someone else if they want to contribute! |
|
This all seems pretty reasonable to me. I'm not really doing an exhaustive review per se since I imagine any bugs will become self-evident pretty quickly. Could you expand a bit on how you think this'll be used in the tooling? For example would we use this to automatically generate polyfills which implement the old function as a call to the new? For cases where it doesn't match up are you thinking we'd automatically polyfill that as well or would we have manually written bindings? |
|
Thanks, I just wanted to get some sort of review so we could get it merged and keep iterating. For tooling, I envision this being used to automatically generate old functions as a call to the new, for cases where it is still compatible. For cases where it doesn't match up, I expect tool users will still have to write bindings by hand - I don't want to take on that more general problem of mapping incompatible calls. I designed this primarily to use in the |
|
👍 |
* feat: add `wasi-0.3.0` draft
Followed the example of `wasi-http` and `wasi-clocks` duplicating the
package in a subdirectory
- Remove `would-block` error code
- Replace `wasi:io/error.error` usage by `error-context`
- Replace `wasi:io/streams.input-stream` return values by `stream<u8>`
in return position
- Replace `wasi:io/streams.output-stream` return values by `stream<u8>`
in parameter position
- Guests should be able to rely on `stream.new` to construct
streams
- Merge `read{,via-stream}` into a singular `read`. Both functions take
an offset as a parameter and since they now return `stream<u8>`,
callers can limit the amount of bytes read by using the `stream<u8>`
directly, therefore functionality of both is identical
- Merge `write{,via-stream}` into a singular `write`. Both functions take
an offset and `stream<u8>` as a parameter.
It is assumed that `error-context` returned by writes to the stream and
reads from the stream are sufficient for error handling.
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
* refactor: avoid introspecting `error-context`
This seems to be better aligned with latest specification on error context
https://github.com/WebAssembly/component-model/blob/cbdd15d9033446558571824af52a78022aaa3f58/design/mvp/Explainer.md#error-context-type
> A consequence of this, however, is that components *must not* depend on the
> contents of `error-context` values for behavioral correctness. In particular,
> case analysis of the contents of an `error-context` should not determine
> *error recovery*; explicit `result` or `variant` types must be used in the
> function return type instead (e.g.,
> `(func (result (tuple (stream u8) (future $my-error)))`).
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
* chore: bump `@since` to `0.3.0`
WebAssembly/wasi-filesystem#164 (comment)
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
* refactor(0.3): simplify error handling
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
* refactor(0.3): asyncify `read-directory`
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
* feat: update wit-deps to 0.5.0
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
* drop `-draft` version suffix
This ensures that e.g.:
```
wit-bindgen markdown wit-0.3.0-draft -w imports --html-in-md
```
works with wit-bindgen 0.37
refs:
WebAssembly/wasi-sockets@3abda6e
refs:
WebAssembly/wasi-sockets#111 (comment)
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
---------
Signed-off-by: Roman Volosatovs <rvolosatovs@riseup.net>
Can we automatically generate polyfills as we upgrade witx? Maybe. Is it worth the trouble? Not sure yet! Seems interesting, though.