WebAssembly/design

Add and remove functions in a module

nepx opened this issue · 4 comments

nepx commented

I've been working on an x86 emulator, which I want to speed up using dynamic recompilation. I would like to target WebAssembly, but there is currently no way to add or remove functions in a module.

I know from #1001 that new modules can be created on the fly, but my problem is that code blocks are almost constantly being created, on the order of several thousand every second. Most modules will usually contain one function (the compiled code) and share the same memory as the main emulator, so it would be overkill to create a new WebAssembly.Module for each one. At the very least, it would eat up a lot of memory.

Compiled blocks are typically not reused because it would take longer to look for a discarded block than to create a new one (while that may seem wasteful, I've found that most blocks are usually less than ten instructions long, so it's not that big of a deal), so it'd be useful to have a way to remove functions as well.

Are you aware of the CheerpX project? (https://www.leaningtech.com/pages/cheerpx.html)

I believe they also perform dynamic recompilation, but far more sparingly. You might find inspiration on how to architect your project from some of their blog posts/presentations.

You could add/remove functions via the table and call_indirect, but I'm not sure if this would be a good solution for you.

Speaking of the table, you can create new JS functions very cheaply and put them in the table for wasm to call. For now, JITing lots of small functions might be best in JS - less memory, and probably just as fast (except for i64s and other specific things).

nepx commented

Thanks for the responses!

@conrad-watt I played with their demo, but right now it seems like it's limited to user-mode POSIX applications, although they say that they plan to virtualize entire operating systems. They say that Chrome dies at 1,000 modules, so I guess that's all the more reason to be able to add functions directly to a module. It seems like they use tail calls to directly link blocks together (which is a cool optimization), but from my experience that leads to a lot of subtle bugs (Windows XP plays a lot of games with the page table during boot, and it broke the direct calls that I was using at the time).

@kripken I've written a JavaScript backend for a toy dynamic recompiler, and it was really clunky (lots of sprintf, strlen) in addition to being very difficult to patch after it was generated. WebAssembly is comparatively simpler, and thus faster, to generate, but for now, I guess JS might be the best (only?) way. 80-bit floating point might be a pain, though.

Still, a way to manipulate the functions in a module would be useful. It seems like this was mentioned in a planned future feature, but what is its status?

binji commented

Still, a way to manipulate the functions in a module would be useful. It seems like this was mentioned in a planned future feature, but what is its status?

There hasn't been anything proposed yet. One concern is that allowing compilation of new functions will break the encapsulation boundary of a WebAssembly module. So perhaps something like the module linking proposal can help here.