bytecodealliance / wasmtime

A fast and secure runtime for WebAssembly
https://wasmtime.dev/
Apache License 2.0
15.3k stars 1.29k forks source link

Cranelift: incremental jit compilation #3624

Open jakubDoka opened 2 years ago

jakubDoka commented 2 years ago

I would like to use the jit module, to compile and run language macros. It would be nice if there a way so serialize the module and just load it next time and overwrite updated functions.

I was thinking about saving the functions as bytes and then reusing these if nothing changed as JitModule does not offer any methods for this purpose. (Is this a good idea?)

The main reason for this is a fact that compiler needs to just build a module tree and skip unchanged branches instead of rejitting everything to achieve incremental build. (building the module tree requires parsing only first item inside a file which is considerably cheaper the building Ast for all items)

bjorn3 commented 2 years ago

Overwriting functions is already supported. First do jit_builder.hotswap(true) when creating the jit module. And then jit_module.prepare_for_function_redefine(func_id) just before calling .define_function() again. Serializing and deserializing jit modules is not currently supported. I would like support for it too, but I am not quite sure about the right api and I haven't had time to implement it yet. For now maybe you could manually call .compile_and_emit() on the Context for each function and then serialize this in whatever format and when deserializing use .define_function_bytes() with the deserialized result of .compile_and_emit()? You will also have to serialize function declarations.

jakubDoka commented 2 years ago

Than you for the quick response.

If it would be welcomed, I could look into jit crate study it a little and make a pr that adds this feature. Of course I already see several problems related to changing a signature of functions. Just to properly handle this, its important to assert that all functions that call the changed function were also reloaded. That, or give responsibility to frontend, since compiler should not even compile the code if you did not change all invocations properly.

So this can be either really easy, or super hard. You can probably tell how much of understanding I need to properly implement this.

When it comes to API I dare say simple serialize and static from_serialized or deserialize, but then again, I have no idea is hidden inside jit source (mostly).