Skip to content
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

Implement value imports/exports and start functions in the component model #4844

Open
alexcrichton opened this issue Sep 1, 2022 · 0 comments
Labels
wasm-proposal:component-model Issues related to the WebAssembly Component Model proposal

Comments

@alexcrichton
Copy link
Member

The current implementation of the component model traked in #4185 is fairly complete with the current state of the spec but a major gap is the implementation of value imports, value exports, and the start function. Currently Wasmtime will panic if any of these constructs are encountered.

@dicej, @jameysharp, @elliottt, and I just had a chat about how we might go about implementing these and we think we have a promising set of ideas which could serve as the basis for implementing all of these features.

Simple case first

One thing we concluded was that tackling the simplest case first is probably the best where there's only one start function in a component and it takes all the imports as parameters. The start function in this case is also the last initializer within the component itself.

To implement this, some rough ideas we had were:

  • A Linker wouldn't actually grow the ability to store values within it, rather Linker::instantiate_pre would grow a new type parameter, U representing the values that the component both imports and exports.
    • For each value imported into a component U would be queried whether it supports a value of that name and of the required type. This would result in a unique index passed to U later at runtime. Part of InstantiatePre would be building a table of these indices.
    • During instantiation U would have methods to "lower the nth argument into this location", either into the stack or into linear memory. The destination would be statically determined prior at component-compile-time and the n passed in would be the result of type-checking in the first step (this is making it so instantiation doesn't do string lookups)
    • Instantiation of InstancePre would take U as an argument and produce U::Result as a result (or something like that)
    • The value results of instantiation would be required to be used prior to the Instance result of instantiation (more on this later in open questions)
  • A new initializer for the start function would be emitted that would know ahead-of-time the canonical ABI and where to lower everything into. This could use the Runtime*Index types to have fast access to memories as well.
    • This initializer would optionally statically record "call malloc with these parameters to get space for the argument lowerings"
    • The initializer would record some precomputed ordering of indices along the lines of "I know ahead of time that U's index for argument "foo" was placed at index 0, so lookup the U index at index 0 and then tell U to lower that at location Y"
  • Value exports could ideally use a somewhat similar scheme of precomputed indexes going through U or something like that. I'm having a harder time planning this out though since instead of the component asking for results it's the constructor of the result asking for names which could be a bit trickier. Hopefully not that much trickier.

Whatever trait U implements is one that we could add a custom derive for. Something like:

#[derive(ValueImports)]
struct MyCustomName {
    #[component(import = "bar")]
    foo: String,
    #[component(import = "foo.bar")] // e.g. an instance import `foo` where the instance exports a value named `bar`
    baz: String,
}

#[derive(ValueExports)]
struct MyCustomName2 {
    #[component(import = "bar")]
    foo: String,
    #[component(import = "foo.bar")] // e.g. an instance export `foo` where the instance exports a value named `bar`
    baz: String,
}

(ok as I write this out I realize that the one U I mentioned above should probably be separate type parameters for both imports and exports)

Inter-component start functions

The next level of cases to handle after the above is implemented would be inter-component start functions where values from one start function flow into values of a different start function within the component graph. This sort of value transfer needs to be entirely handled by the precompiled artifact since the embedder is not even aware of the types involved here.

For this the rough assumption is that the usage of fact should be somewhat easy to do here. Ideally this could leverage most of what fact already implements but at least to me it's not immediately obvious how this would be done. @jameysharp's idea was that we could model the start functions as a combination of the primitives that fact implements already today, although I don't think we came to a conclusion on exactly what these primitives are or what the combinations look like.

Open questions

  • I opened this issue to clarify but I'm at least personally not sure when it's safe to consider a return value of a start function either valid or invalid. Especially with post-return it's not clear when to invoke post-return I think right now or when it's possible to reenter the instance. If reentering an instance is possible then we need to buffer the return value somewhere, but I don't think we want to be required to do that design-wise so I think some spec work may be necessary to flesh out the cases about dealing with return values and if/when a component can be reentered. (as the issue title suggest this probably 100% boils down to "when is the post-return function called?")
@alexcrichton alexcrichton added the wasm-proposal:component-model Issues related to the WebAssembly Component Model proposal label Sep 1, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
wasm-proposal:component-model Issues related to the WebAssembly Component Model proposal
Projects
None yet
Development

No branches or pull requests

1 participant