mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-20 16:26:33 +00:00
Add experimental support for the anyref
type
This commit adds experimental support to `wasm-bindgen` to emit and leverage the `anyref` native wasm type. This native type is still in a proposal status (the reference-types proposal). The intention of `anyref` is to be able to directly hold JS values in wasm and pass the to imported functions, namely to empower eventual host bindings (now renamed WebIDL bindings) integration where we can skip JS shims altogether for many imports. This commit doesn't actually affect wasm-bindgen's behavior at all as-is, but rather this support requires an opt-in env var to be configured. Once the support is stable in browsers it's intended that this will add a CLI switch for turning on this support, eventually defaulting it to `true` in the far future. The basic strategy here is to take the `stack` and `slab` globals in the generated JS glue and move them into wasm using a table. This new table in wasm is managed at the fringes via injected shims. At `wasm-bindgen`-time the CLI will rewrite exports and imports with shims that actually use `anyref` if needed, performing loads/stores inside the wasm module instead of externally in the wasm module. This should provide a boost over what we have today, but it's not a fantastic strategy long term. We have a more grand vision for `anyref` being a first-class type in the language, but that's on a much longer horizon and this is currently thought to be the best we can do in terms of integration in the near future. The stack/heap JS tables are combined into one wasm table. The stack starts at the end of the table and grows down with a stack pointer (also injected). The heap starts at the end and grows up (state managed in linear memory). The anyref transformation here will hook up various intrinsics in wasm-bindgen to the runtime functionality if the anyref supoprt is enabled. The main tricky treatment here was applied to closures, where we need JS to use a different function pointer than the one Rust gives it to use a JS function pointer empowered with anyref. This works by switching up a bit how descriptors work, embedding the shims to call inside descriptors rather than communicated at runtime. This means that we're accessing constant values in the generated JS and we can just update the constant value accessed.
This commit is contained in:
@ -35,6 +35,7 @@ pub struct Bindgen {
|
||||
// Experimental support for the wasm threads proposal, transforms the wasm
|
||||
// module to be "ready to be instantiated on any thread"
|
||||
threads: Option<wasm_bindgen_threads_xform::Config>,
|
||||
anyref: bool,
|
||||
}
|
||||
|
||||
enum Input {
|
||||
@ -62,6 +63,7 @@ impl Bindgen {
|
||||
emit_start: true,
|
||||
weak_refs: env::var("WASM_BINDGEN_WEAKREF").is_ok(),
|
||||
threads: threads_config(),
|
||||
anyref: env::var("WASM_BINDGEN_ANYREF").is_ok(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,6 +178,22 @@ impl Bindgen {
|
||||
(module, stem)
|
||||
}
|
||||
};
|
||||
|
||||
// This isn't the hardest thing in the world too support but we
|
||||
// basically don't know how to rationalize #[wasm_bindgen(start)] and
|
||||
// the actual `start` function if present. Figure this out later if it
|
||||
// comes up, but otherwise we should continue to be compatible with
|
||||
// LLVM's output today.
|
||||
//
|
||||
// Note that start function handling in `js/mod.rs` will need to be
|
||||
// updated as well, because `#[wasm_bindgen(start)]` is inserted *after*
|
||||
// a module's start function, if any, because we assume start functions
|
||||
// only show up when injected on behalf of wasm-bindgen's passes.
|
||||
if module.start.is_some() {
|
||||
bail!("wasm-bindgen is currently incompatible with modules that \
|
||||
already have a start function");
|
||||
}
|
||||
|
||||
let mut program_storage = Vec::new();
|
||||
let programs = extract_programs(&mut module, &mut program_storage)
|
||||
.with_context(|_| "failed to extract wasm-bindgen custom sections")?;
|
||||
@ -233,7 +251,10 @@ impl Bindgen {
|
||||
imported_statics: Default::default(),
|
||||
direct_imports: Default::default(),
|
||||
start: None,
|
||||
anyref: Default::default(),
|
||||
};
|
||||
cx.anyref.enabled = self.anyref;
|
||||
cx.anyref.prepare(cx.module)?;
|
||||
for program in programs.iter() {
|
||||
js::SubContext {
|
||||
program,
|
||||
|
Reference in New Issue
Block a user