You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Right now there are two potential kinds of tables:
funcref tables
externref tables
The latter are easy to support, since Wasm can't construct an externref, only receive it from the outside world. As long as we don't allow any externrefs into the Wasm during initialization, then all we have to do is record the initialized size of these tables.
funcref tables are a little harder. Wasm can create funcrefs via the ref.func instruction. So we need a way to figure out which function each wasmtime::FuncRef in a table we are snapshotting is (i.e. what is the local function index of the ith table element?). wasmtime doesn't expose anything like that. I have an idea, however:
during Wizer's instrumentation phase:
add two new globals to the module: $wizer_getting_func_index and $wizer_func_index
add the following snippet to the start of every function in the module:
block
global.get $wizer_getting_func_index
i32.eqz
br_if 0
i32.const <this function's local index>
global.set $wizer_func_index
unreachable
end
then, during snapshotting, to get a given funcref's local function index, we set the $wizer_getting_func_index global non-zero, call the function, and then it will set its local function index to the $wizer_func_index global and trap.
the dummy functions we create for imports will need a similar dance, but implemented in native code rather than Wasm. Something similar for wasi functions too.
The one problem is that local function index isn't quite enough in the face of module linking. Instead we will need both the instance "id" (whatever that this; DFS index?) as well as the local function index in that instance. More to think about w.r.t. module linking here...
The one problem is that local function index isn't quite enough in the face of module linking. Instead we will need both the instance "id" (whatever that this; DFS index?) as well as the local function index in that instance. More to think about w.r.t. module linking here...
We can flip our view of this problem to make it a lot easier: we don't need to know, for a given table, where all of its functions came from and how to get them in there. Because of the constraints that Wizer imposes on imports, we know that all the functions came from somewhere inside this module graph / instantiation tree. So each instance needs to ask for a given table that it has access to, which of these functions are from me? Then we save this info in the snapshot and emit them as element segments.
We can make this a little more efficient by associating a bitmap with each table of which functions we've already resolved, so we don't have to check every single function in the table for every instance that has access to that table. This would also let us catch errors where some future WASI proposal stuffed things into the function table, or if we supported initializing with arbitrary linkers: just assert that we checked off all bits in that bit map, meaning we've accounted for every function in the table.
Right now there are two potential kinds of tables:
funcref tables
externref tables
The latter are easy to support, since Wasm can't construct an externref, only receive it from the outside world. As long as we don't allow any externrefs into the Wasm during initialization, then all we have to do is record the initialized size of these tables.
This might cause us inconvenience if/when we support gc, as gc supports conversion between ref any and ref extern.
funcref tables are a little harder. Wasm can create funcrefs via the ref.func instruction. So we need a way to figure out which function each wasmtime::FuncRef in a table we are snapshotting is (i.e. what is the local function index of the ith table element?). wasmtime doesn't expose anything like that. I have an idea, however:
during Wizer's instrumentation phase:
add two new globals to the module: $wizer_getting_func_index and $wizer_func_index
add the following snippet to the start of every function in the module:
block
global.get $wizer_getting_func_index
i32.eqz
br_if 0
i32.const <this function's local index>
global.set $wizer_func_index
unreachable
end
then, during snapshotting, to get a given funcref's local function index, we set the $wizer_getting_func_index global non-zero, call the function, and then it will set its local function index to the $wizer_func_index global and trap.
the dummy functions we create for imports will need a similar dance, but implemented in native code rather than Wasm. Something similar for wasi functions too.
We could also wrap imports in a shim that does the instrumentation code, then calls it and returns.
The one problem is that local function index isn't quite enough in the face of module linking. Instead we will need both the instance "id" (whatever that this; DFS index?) as well as the local function index in that instance. More to think about w.r.t. module linking here...
Module linking was replaced by the component model, so this might be feasible again, as wizercurrently doesn't support it.
Activity
fitzgen commentedon Sep 1, 2021
We can flip our view of this problem to make it a lot easier: we don't need to know, for a given table, where all of its functions came from and how to get them in there. Because of the constraints that Wizer imposes on imports, we know that all the functions came from somewhere inside this module graph / instantiation tree. So each instance needs to ask for a given table that it has access to, which of these functions are from me? Then we save this info in the snapshot and emit them as element segments.
We can make this a little more efficient by associating a bitmap with each table of which functions we've already resolved, so we don't have to check every single function in the table for every instance that has access to that table. This would also let us catch errors where some future WASI proposal stuffed things into the function table, or if we supported initializing with arbitrary linkers: just assert that we checked off all bits in that bit map, meaning we've accounted for every function in the table.
gkgoat1 commentedon Jan 30, 2025
This might cause us inconvenience if/when we support gc, as gc supports conversion between
ref anyandref extern.We could also wrap imports in a shim that does the instrumentation code, then calls it and returns.
Module linking was replaced by the component model, so this might be feasible again, as
wizercurrently doesn't support it.