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

How should I access the WebAssembly.Memory instance? #19832

Open
kg opened this issue Jul 10, 2023 · 17 comments
Open

How should I access the WebAssembly.Memory instance? #19832

kg opened this issue Jul 10, 2023 · 17 comments

Comments

@kg
Copy link

kg commented Jul 10, 2023

I'm jitting WASM modules inside of a running emscripten-compiled application, which means I need to grab the function table and heap to share them with the jitted code.

In a single-threaded app this seems to work fine, but I'm having trouble getting the Memory object in a threaded app. I've been doing Module["asm"]["memory"] but that doesn't seem to work. How should I be doing this? Looking through the code in the emscripten repo I wasn't able to figure it out.

EDIT: To be clear, in the threaded app I get 'error: memory import must be a WebAssembly.Memory object'.

@kripken
Copy link
Member

kripken commented Jul 11, 2023

I think wasmMemory should always exist:

var wasmMemory;

It might get renamed or such as this isn't a public API, but in general it should be ok to use.

@kg
Copy link
Author

kg commented Jul 11, 2023

I think wasmMemory should always exist:

var wasmMemory;

It might get renamed or such as this isn't a public API, but in general it should be ok to use.

I'm guessing I'll need to explicitly export this like the functions from preamble?

@kripken
Copy link
Member

kripken commented Jul 11, 2023

If you want to access it from outside of the Emscripten JS, then yes. Using -sEXPORTED_RUNTIME_METHODS=wasmMemory should work I think.

@kg
Copy link
Author

kg commented Jul 11, 2023

If you want to access it from outside of the Emscripten JS, then yes. Using -sEXPORTED_RUNTIME_METHODS=wasmMemory should work I think.

Doesn't seem to be working, maybe it needs to be an accessor function?

@kripken
Copy link
Member

kripken commented Jul 11, 2023

Hmm, maybe I'm not sure how you are trying to use it? This is the impact of that flag:

$ ./emcc test/hello_world.c -O3 --profiling

$ ./emcc test/hello_world.c -O3 --profiling -o b.out.js -sEXPORTED_RUNTIME_METHODS=wasmMemory

$ diff a.out.js b.out.js
276c276
< wasmBinaryFile = "a.out.wasm";
---
> wasmBinaryFile = "b.out.wasm";
496a497,498
> 
> Module["wasmMemory"] = wasmMemory;

That flag exports it, so accessing Module.wasmMemory should now work. Are you trying to use it some other way?

@kg
Copy link
Author

kg commented Jul 11, 2023

I've tried Module["wasmMemory"] and Module["asm"]["wasmMemory"] and they're both undefined in a single-threaded build. I added wasmMemory to the list of exported runtime methods right next to ccall, cwrap, etc. I'll see if maybe something is wrong with our build system.

@sbc100
Copy link
Collaborator

sbc100 commented Jul 11, 2023

Are you using -sMODULARIZE? Otherwise I would have though you could just use wasmMemory on its own (i.e. not hanging off the Module object at all?)

If you are using -sMODULARIZE I have a patch that I think will make -sEXPORTED_RUNTIME_METHODS=wasmMemory work as expected: #19816

@sbc100
Copy link
Collaborator

sbc100 commented Jul 11, 2023

Specifically the maybeExport part of the PR is what will fix -sEXPORTED_RUNTIME_METHODS=wasmMemory I believe.

@sbc100
Copy link
Collaborator

sbc100 commented Jul 11, 2023

Also, I guess Module.HEAPU8.buffer is not good enough for your purposes?

@kg
Copy link
Author

kg commented Jul 11, 2023

I found our .rsp file and it contains:

-s EXPORTED_RUNTIME_METHODS="['FS','out','err','ccall','cwrap','setValue','getValue','UTF8ToString','UTF8ArrayToString','stringToUTF8Array','FS_createPath','FS_createDataFile','removeRunDependency','addRunDependency','addFunction','safeSetTimeout','runtimeKeepalivePush','runtimeKeepalivePop','maybeExit','wasmMemory']"

So I think I'm doing the right thing. Your PR looks good to me.

I haven't tried Module.HEAPU8.buffer, would that be a WebAssembly.Memory object? I assumed it might be a SharedArrayBuffer or something else unacceptable to the runtime.

@kg
Copy link
Author

kg commented Jul 11, 2023

Are you using -sMODULARIZE? Otherwise I would have though you could just use wasmMemory on its own (i.e. not hanging off the Module object at all?)

If you are using -sMODULARIZE I have a patch that I think will make -sEXPORTED_RUNTIME_METHODS=wasmMemory work as expected: #19816

Yeah, checking the rsp we are compiling in modularized mode.

@sbc100
Copy link
Collaborator

sbc100 commented Jul 11, 2023

-sEXPORTED_RUNTIME_METHODS=wasmMemory won't work as expected today (without my PR) since that exports is created before its gets assigned (after instantiation).

@sbc100
Copy link
Collaborator

sbc100 commented Jul 11, 2023

i.e. Module["wasmMemory"] = wasmMemory; is just exporting undefined (at least for async compilation).

@kg
Copy link
Author

kg commented Jul 11, 2023

i.e. Module["wasmMemory"] = wasmMemory; is just exporting undefined (at least for async compilation).

An accessor function like getMemory() would fix this, since it would get the current value, right?

@sbc100
Copy link
Collaborator

sbc100 commented Jul 11, 2023

Indeed, and in fact and accessor function would be necessary if one wanted to import it like import { wasmMemory } from ..

For the time being it would get easy to just write your own accessory function in --js-library .. or --pre-js file.

@kg
Copy link
Author

kg commented Jul 19, 2023

I managed to get somewhere by exporting an accessor in my pre js, but I'm getting an error I don't know how to make sense of:

code generation failed: LinkError: WebAssembly.Instance(): mismatch in shared state of memory, declared = 0, imported = 1 LinkError: WebAssembly.Instance(): mismatch in shared state of memory, declared = 0, imported = 1

Is this something I need to change in my emcc configuration, or do I need to change how I'm generating my modules?

@kg
Copy link
Author

kg commented Jul 19, 2023

Ah, I see the binary encoding for memory limits was changed to add a new shared flag, so that's what I'm missing. And it looks like the module now will have an explicit maximum memory size and I'll need to match it when generating... so I'll need to make sure I have a way to match what emcc generates there.

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

No branches or pull requests

3 participants