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

Add the ability to avoid emitting mutable globals. #2386

Closed
arilotter opened this issue Dec 3, 2020 · 5 comments
Closed

Add the ability to avoid emitting mutable globals. #2386

arilotter opened this issue Dec 3, 2020 · 5 comments

Comments

@arilotter
Copy link
Contributor

arilotter commented Dec 3, 2020

Motivation

Exported mutable globals were not a thing in MVP WebAssembly, but are now part of the spec.
Since version 0.2.66, wasm-bindgen has generated WebAssembly that uses mutable globals, but not all WebAssembly engines in the wild support the mutable globals part of the spec:
e.g. iOS 12 by virtue of shipping WebKit with OS updates (so every iPhone <= iPhone 6), Firefox ESR 60, and Node.js 10 all don't support mutable globals. They run binaries made with wasm-bindgen <= 0.2.65 without mutable globals perfectly fine.

This means that you'll never be able to run WebAssembly binaries compiled with recent and future versions of wasm-bindgen on those platforms.

My company would like to support the iPhone 6, and I know that we're not the only ones using Rust that would like to run WebAssembly binaries on engines without the mutable globals feature, and thus being forced to pin to wasm-bindgen version 0.2.65:
zotero/citeproc-rs@e0a3bdd
cloudflare/rustwasm-worker-template@fe5ce45
chitalian/wasm-pack-template@46f988e
zakhenry/mesh-to-svg@9597aec
Emurgo/cardano-serialization-lib@02432d5
p2panda/p2panda@43d81b3

Proposed Solution

Add a flag --disable-mutable-globals to explicitly disable emitting mutable globals. If wasm-bindgen needs to export a variable in a way that's globally writable, wasm-bindgen should emit a setter instead.

At least one other project outside the Rust ecosystem implemented a similar workaround (emitting setters instead of mutable globals) to maintain backwards compatibility with older implementations of the WebAssembly spec:
AssemblyScript/assemblyscript@e03b71d

Alternatives

The only alternative to implementing this feature, if we want to keep supporting the aforementioned WebAssembly engines, seems to be pinning wasm-bindgen's version to =0.2.65. This is really not great, since we're then stuck on that version indefinitely.

@alexcrichton
Copy link
Contributor

Thanks for the report! I didn't expect this to be so much of a problem in practice, but if that's the case then it should be quite easy to work around this. I think the best route would not be to not use a flag but rather instead just always inject the shim functions like AssemblyScript does. It should be relatively easy to add with walrus!

@arilotter
Copy link
Contributor Author

@alexcrichton That's great to hear! I'd be happy to try and implement this myself if you can give me a couple pointers as to where to start adding this walrus pass to replace mutable globals with shims :)

@alexcrichton
Copy link
Contributor

Ok great! The meat of what happens is here as that's the only place that needs the mutable global exported. I think this can be fixed by adding a function like __wbindgen_add_to_stack_pointer(i32) -> i32 where it'd add the provided value and return the previous or the current value (whichever is more relevant for this context).

The actual addition of the function would probably best be handled as a method on Context. That'd lazily add the new shim function to self.module. You can probably have a bool or something on Context as to whether it's been generated yet.

Actual creation of the function would use FunctionBuilder and you can see an example of that around here. It should be fine to eschew tests as well since this either works or all the tests will break :)

@stuartZhang
Copy link

Which version will include the improvement? I need it as well. @alexcrichton

@arilotter
Copy link
Contributor Author

@stuartZhang The fix was included in wasm-bindgen 0.2.70

I can confirm that with that release, my binaries started working again on iPhone 6! Thanks, Alex, for all the guidance in helping me solve this issue :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants