If you're compiling to WASM with the Emterpreter, the Emterpreter data is not embedded within the WASM and is either left as a standalone file, or embedded as an array in the JS.
The WASM spec allows you to have multiple data sections, and the Emterpreter data is just being set in the main heap, so it should be possible to have it embedded in the WASM, right?
Also, the helpful error for when you forget to load the data file Assertion failed: bad emterpreter file in -O0 turns into the much less clear failed to asynchronously prepare wasm: RuntimeError: remainder by zero in -O3.
Good idea, this would be useful to do.
About those errors, do you have a testcase showing them?
What form of testcase would be most useful for you?
I could very easily make two branches to checkout of my moderate sized project with the -O setting changed, and then all you'd need to do is run make, if that would be enough.
Yeah, that would be enough. Just as long as it's a simple checkout + run make (i.e. I don't need to install a build system or other tools).
I was able to make a minimal test case: https://gist.github.com/curiousdannii/07f1d750226befd4cbf6d858f204ac94
The -O3 error message is different however: failed to asynchronously prepare wasm: RuntimeError: memory access out of bounds
I tried to debug this in the spidermonkey shell, where the error is different. It works without the emterpreter file, but with it, it fails. Looks like it hits this assertion:
var bytecodeFile = Module['emterpreterFile'];
assert(bytecodeFile instanceof ArrayBuffer, 'bad emterpreter file');
Looking in the docs, it says
src/settings.js: // When emitting HTML, we automatically generate code to load this file and set it to Module.emterpreterFile. If you
src/settings.js: // emit JS, you need to make sure that Module.emterpreterFile contains an ArrayBuffer with the bytecode, when the code loads.
So looks like the user needs to set that file, since we compiled to JS and not HTML. Maybe that's the problem you were hitting?
So looks like the user needs to set that file, since we compiled to JS and not HTML. Maybe that's the problem you were hitting?
Yeah, but the issue is that the explicit error message is shown in -O0, but in -O3 (I think actually -O1+) the error message isn't shown, and some other WASM loading error is shown.
Or is this by design - error messages like this are only meant to be shown when assertions are on? If so, then I think missing file errors like this deserve being made normal errors and shown even when assertions are off. FWIW the memory loader throws normally.
If #5104 was resolved through a centralised loading system then we wouldn't need to have multiple places checking and throwing errors. :)
I agree, an error like that should be handled even when assertions are off. We should replace the assert on it with a check and call of abort, PR would be welcome.
According to the WASM spec this may not be possible yet:
In the current version of WebAssembly, at most one memory is allowed in a module. Consequently, the only valid memidxmemidx is 00.
It's true we can't embed it as a new memory, but we can enlarge the existing single memory and add it into there. We also need to update the static-bump stuff so the compiler knows that we are using more memory statically.
I'd be interested in working on this, but I think it will probably end up being beyond me.
I took a look, and I couldn't see any sort of general purpose wasm embedder.
Two options I can see:
I think the first is probably better, but it would require me to dig into the binaryen source, whereas the second may potentially be doable just in emcc.py.
Option 2 would only be practical once we emit wasms with relocation info, as that info would contain the "static bump" metadata that is necessary for such merging, I'm afraid.
And I think there is a better option than Option 1. Look at make_shared_library in tools/shared.py, it reads the STATIC_BUMP info from the JS (going back to the previous paragraph, in the future it could read it from the wasm object file metadata). So it's practical to read and write the bump (currently, at least before the JS is minified), and so the emterpretify code could append the emterpreter binary code into the mem init file, after the current static bump (appending zeros first if necessary), and then increase the static bump in the JS.
(And then the mem init file would get imported into the wasm normally, in asm2wasm, so there is no wasm-specific code here. But, it might be simpler to do this in a wasm-only way, as when we minify the JS might be different, so ignoring the asm.js case is fine.)
This issue has been automatically marked as stale because there has been no activity in the past year. It will be closed automatically if no further activity occurs in the next 7 days. Feel free to re-open at any time if this issue is still relevant.