-
Notifications
You must be signed in to change notification settings - Fork 1
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
Identify start function in CM thread.spawn
with an index
#89
Comments
Can you elaborate on this part? What are the different relevant stages and why does the type index change? There is a relocation I suspect that part of the problem is that core Wasm doesn't support type parameters at all, and the component model probably doesn't want to be in the business of introducing them. Another option would be to make the type of the parameter In general the idea of creating |
Re 2: Wouldn't this require a table index immediate? Why is that easier to handle than a type index? Re 3: Wouldn't spawn_indirect need a type index immediate as well? Similarly any solution using funcref? AFAICS, somehow the intended type has to be (statically) derivable, so some form of immediate appears to be unavoidable. |
To clarify a bit on why things are hard right now for wasmtime/wasm-tools, the precise reasons are pretty specific to the design of the two libraries themselves. The exact details are a bit much to put in this thread, but the general gist is that the full matrix of interactions of the GC proposal of WebAssembly and the component model have not all been fleshed out previously in Wasmtime. That's being stressed here with today's The other rationale we have for not using a function-reference-based-approach is that LLVM-based tooling basically isn't ready for that. AFAIK there's no way, today, to import the I believe Nick and I were advocating for (3) here where we're not saying that And yes, |
Well, call_indirect has both a type and a table index. It's not clear to me how spawn_indirect could get around that? |
|
@tlively, well yes, but isn't that orthogonal, and you could do the same with a ref? Not sure I follow how call_indirect helps. |
Right, that's why I suggested that another short-term solution would be to use |
Even if the parameter itself was funcref, you'd need to annotate its expected type somehow, otherwise the expected operand count and types wouldn't be known to the validator. Unless they're hardcoded in the semantics, but then there's no point in using funcref either. So again, I can't see how any of these options solves anything. |
Why not? It still lets you dynamically choose which function to spawn the thread with, as long as it has the expected signature. |
Yes, but what's the advantage over the status quo using a typed reference? |
LLVM-based tooling would have a much easier time dealing with a funcref than dealing with a typed function reference. |
@alexcrichton, I can't quite tell from your comment whether you are referring to function references in the signature generally being problematic for LLVM, or typed function references in particular. Can you clarify? |
Personally I find both problematic. While LLVM tooling handles I'll reiterate I understand why the spec-level definition of this function takes a typed-function or a generic |
That sounds perfectly fine to me 👍 |
If the compilation scheme from rust with an "indirect table-style" operation would succeed, could the
Is there a standard way of doing this in the CM (e.g. encoding the index in the import name)? |
Indeed! That would be more toolchain things to update to get to the point where things could be evaluated, so I could also understand if @abrown doesn't want to implement that quite just yet, but to me that's a possible argument for never standardizing the
Not currently unfortunately. Each intrinsic is a bit different from all the others in what it needs and what it can reference, so it's mostly a loose set of conventions right now for how components are created from core wasm modules. For example if you import a function that takes a string then the string has to be in some linear memory, and right now it's implicitly the export |
@alexcrichton, do you mean |
Yes that's what I've been thinking. I don't speak for Andrew though, so he might be thinking something else.
Personally I think this is debatable, not "obvious", but I'm happy to defer discussion of such to after experimentation/evaluation has been done. |
Here's what I'm thinking: I'm trying to carefully balance "moving this forward" with "doing things right." I remember how wasi-threads was "good enough" and that turned out to be a problem; it was a great experiment, but because it was good enough for some, it stuck around longer than others would have liked. If I create yet another prototype and it is "good enough," the low-level nature of this stuff and the prevalence of wasi-libc as a starting point could make it stick. So this time around it would be great if this spawn function signature was "right" from the beginning, since I expect more thrash on the thread local side of this anyways. We've previously discussed a completely static I am struggling to find the right balance here given the limitations of the toolchains, CM, state of implementation, etc. E.g.: is there really a way here to both move this forward and not permanently bake in "C"-centrism? |
Is there another mechanism you can use to prevent people from using experimental features in production? Only enable it if an |
There probably is, but I guess I'm hoping this "start function" problem isn't the one to do that for. Maybe we just have to go with the C-like table + index approach... perhaps we should discuss in the next meeting? |
The overview references issues #3 and #10 on this, which contains some of the discussion that I remember. An index is fine for experiments, but baking it in long-term would be an awful hack, and highly biased one. If we go with that then I agree that we should find some way to make sure that it won't stuck. |
@rossberg, we discussed this in the threads subgroup today (a shame you couldn't attend!). Notes from the meeting are available here, but let me attempt to summarize where I ended up on this after the discussion:
|
Ah, thanks @brown for the summary. Looks like I missed the meeting again. @tlively, can we please make sure that all meetings and their agendas are in the meetings repo? We shouldn't expect people to crawl issue lists across N repos to figure out what meetings are on. As for the subject of discussion: having spawn_indirect with a restricted signature is okay with me, as long as it remains forward-compatible to general type signatures. But I definitely think we need to have spawn_ref and a generalised spawnee type in the future — perhaps along with the component model properly supporting GC types. Because tables and memory do not make much sense for a reference- and GC-based language runtime, nor does a i32-based (i.e., pointer-based) spawn signature. |
To clarify my position: I am in favor of spec'ing both And as an intermediate, stepping-stone implementation state for purposes of expediently getting prototypes of a subset of everything we intend to spec into the hands of toolchains and early experimenters to play with, I am encouraging Andrew to start with implementing just the |
As discussed in [bytecodealliance#89], this adds support for a new intrinsic, `thread.spawn_indirect`. This new operation would allow spawning a shared function stored in a table via a table index. This leaves some future work undone: - `thread.spawn` could/should be renamed to `thread.spawn_ref` - `thread.spawn_indirect` could/should take the encoding byte from `thread.hw_concurrency`--swap `0x07` for `0x06` - importantly, `thread.spawn_indirect` should gain a field indicating which type to expect in the indirect table; due to current limitations in `wasm-tools`, the locations to check once this is possible are marked with `TODO: spawn indirect types`. [bytecodealliance#89]: WebAssembly/shared-everything-threads#89
As discussed in [bytecodealliance#89], this adds support for a new intrinsic, `thread.spawn_indirect`. This new operation would allow spawning a shared function stored in a table via a table index. This leaves some future work undone: - `thread.spawn` could/should be renamed to `thread.spawn_ref` - `thread.spawn_indirect` could/should take the encoding byte from `thread.hw_concurrency`--swap `0x07` for `0x06` - importantly, `thread.spawn_indirect` should gain a field indicating which type to expect in the indirect table; due to current limitations in `wasm-tools`, the locations to check once this is possible are marked with `TODO: spawn indirect types`. [bytecodealliance#89]: WebAssembly/shared-everything-threads#89
This change codifies the conclusions we arrived to in [WebAssembly#89]. It adds a new way to spawn threads, `thread.spawn_indirect`, which retrieves the thread start function from a table. This prompted me to rename `thread.spawn` to `thread.spawn_ref`. [WebAssembly#89]: WebAssembly/shared-everything-threads#89
This change codifies the conclusions we arrived to in [WebAssembly#89]. It adds a new way to spawn threads, `thread.spawn_indirect`, which retrieves the thread start function from a table. This prompted me to rename `thread.spawn` to `thread.spawn_ref`. [WebAssembly#89]: WebAssembly/shared-everything-threads#89
As discussed in [bytecodealliance#89], this adds support for a new intrinsic, `thread.spawn_indirect`. This new operation would allow spawning a shared function stored in a table via a table index. This leaves some future work undone: - `thread.spawn` could/should be renamed to `thread.spawn_ref` - `thread.spawn_indirect` could/should take the encoding byte from `thread.hw_concurrency`--swap `0x07` for `0x06` - importantly, `thread.spawn_indirect` should gain a field indicating which type to expect in the indirect table; due to current limitations in `wasm-tools`, the locations to check once this is possible are marked with `TODO: spawn indirect types`. [bytecodealliance#89]: WebAssembly/shared-everything-threads#89
When designing this proposal's integration with the component model (CM), we decided to pass the start function as a reference to the CM's
thread.spawn
intrinsic. IIRC, this avoided the issue of forcing the creation of ashared
table to contain thestart
function. But, while doing pathfinding implementation to vet these design choices, I discovered that there are missing pieces inwasm-tools
that make this "passstart
as a reference" very difficult.@alexcrichton and @fitzgen can correct me here if I'm not explaining this correctly, but my take is that the implementations in
wasm-tools
and Wasmtime don't have the necessary plumbing to refer to a CMcore type
from within a separate CMcore module
. No other CM intrinsics besidesthread.spawn
refer to a type declared elsewhere (see$ft
here); if we are to pass a reference, we need a type for that reference and that type has an index, but not necessarily the same index, at different stages in the toolchain. @alexcrichton and @fitzgen tell me that adding the necessary index conversions for this new intrinsic inwasm-tools
and Wasmtime is too much work; their recommendation is to switch thethread.spawn
intrinsic to receive ani32
instead.At this point, this issue is a roadblock before implementing enough to experiment with different TLS design options, which is what I believe needs more focused attention. The necessary bits are implemented in
wasm-tools
but this problem of "how to pass thestart
function" must to be resolved to have a working implementation in Wasmtime. Here are some options to resolve this:wasm-tools
and Wasmtime; @alexcrichton and @fitzgen tell me this is the least desirable choicethread.spawn
:[f: (ref null $f) n:i32 c:i32]
would become[f: i32 n: i32, c: i32]
thread.spawn_indirect
, with the new signature[f: i32 n: i32, c: i32]
Note that I am attempting to get this all working in wasi-libc, where one would expect that C function pointers would be placed in a table anyways. It's not clear to me that if we adopted 3 how we might implement the current version of
thread.spawn
and who would be using it, given how most projects tend to build on top wasi-libc.The text was updated successfully, but these errors were encountered: