proposal-type-imports icon indicating copy to clipboard operation
proposal-type-imports copied to clipboard

Could type exports export result types?

Open PoignardAzur opened this issue 6 years ago • 5 comments

This question is related to the general problem of cross-module capabilities.

In the inter-module bindings proposal, @lukewagner and I discussed the possibility of implementing some of the mentioned features in existing proposals.

The main feature I proposed is having modules export value types or even result types (eg i32, [i64, i64]) as abstract types with lifetime hooks.

While it's been established that this proposal doesn't cover abstract types, I wonder if it could be extended from allowing exports of constype, to allowing exports of arbitrary valtype or resulttype?

I'm especially interested in knowing how difficult this would be to integrate into existing wasm implementations.

PoignardAzur avatar Aug 12 '19 14:08 PoignardAzur

Unfortunately, importing non-reference types would pretty much break (separate) compilation of Wasm modules, since the engine could not know what the space and storage constraints for values of an imported type are, what barriers or other guard/trace mechanisms it would need to compile in where such values are accessed, or what stack maps to produce. So this would be pretty much incompatible with Wasm's compile/instantiate separation, AFAICS.

rossberg avatar Aug 12 '19 15:08 rossberg

That's a bummer.

The obvious solution I see for OCAP is having the importing module bake knowledge about the type's ABI in its import, eg

(import "gameEngine" "Entity" (type $GameEntity) using i64)

so the importing module knows the types it's importing, but "pretends" not to, enforced by the host.

It's kind of flimsy though.

PoignardAzur avatar Aug 12 '19 15:08 PoignardAzur

The obvious alternative is boxing all capability values, which might well be the simplest solution.

rossberg avatar Aug 12 '19 15:08 rossberg

True.

Downsides:

  • It shackles module interop to GC.
  • It adds one level of indirection to every capability access.
  • It doesn't allow tight lifecycle hooks (eg incref/decref); though in practice, that can be alleviated with manual (compiler-assisted) memory management.

Upsides:

  • It fits into existing semantics.
  • It doesn't require recompiling a module every time its dependency's ABI changes.

PoignardAzur avatar Aug 12 '19 15:08 PoignardAzur

Importing non-reference types is something we need to support in the long term. I think it's OK to have a restriction for now, but type imports are a form of type parameters that almost certainly will be used (abused?) for generic programming in the future. E.g. just think of a utilities module offering a generic Vector<T> type; of course it useful to allow Vector, and could be accomplished if the module has an unrestricted type import T.

Compilation is semantically invisible, yet an implicit performance and space guarantee throughout our design process. Separate AOT compilation can still be supported if we further break up the compile/instantiate phases. For example, the engine really only needs to know the machine representation of a type in order to generate machine code. So it is possible to add a "pre-instantiate" phase where the engine is provided only the machine representations of type imports (not the actual types themselves), in order to get a module actually compiled to machine code and cached. That module than then be instantiated with any actual types that are compatible with the machine representations that were provided in the pre-instantiate phase. There are only a finite number of machine representations (i32, i64, f32, f64, simd128, externref, funcref), so this is manageable, IMO.

titzer avatar Jul 15 '20 03:07 titzer