简体   繁体   English

是否可以将新的 function 添加到实例化的 Webassembly 模块?

[英]Is it possible to add a new function to an instantiated Webassembly module?

I'm writing a wasm program that will dynamically generate wasm functions as bytecode (including the type signature, locals vector, and body instruction sequence; everything that defines a function according to the spec ).我正在编写一个 wasm 程序,它将动态生成作为字节码的 wasm 函数(包括类型签名、本地向量和主体指令序列; 根据规范定义 function 的所有内容)。 I want an efficient way to execute these functions (ie be able to obtain a funcref to them) from within an already-instantiated, running module.我想要一种从已经实例化的正在运行的模块中执行这些函数的有效方法(即能够获得它们的funcref )。

It seems like most implementations do this sort of thing by simply creating a new module out of the generated code, hooking up the necessary imports, and then invoking the new module from JavaScript.似乎大多数实现都是通过简单地从生成的代码中创建一个新模块,连接必要的导入,然后从 JavaScript 调用新模块来完成这类事情。

I need to do it without JavaScript, and ideally without creating a new module either.我需要在没有 JavaScript 的情况下完成它,理想情况下也不需要创建新模块。 It seems like this should be doable in a relatively simple way:看起来这应该以一种相对简单的方式可行:

  1. Just add the new function to the current module's existing vector of functions, with a new funcidx .只需将新的 function 添加到当前模块的现有函数向量中,并使用新的funcidx Obviously, care must be taken to ensure the generated code references other functions, globals, imports etc. by their appropriate indices.显然,必须注意确保生成的代码通过其适当的索引引用其他函数、全局变量、导入等。
  2. Reference the new function by it's new funcidx , including calling ref.func to get a funcref to call it indirectly.通过它的新 funcidx 引用新的funcidx ,包括调用ref.func以获取funcref以间接调用它。

Based on my understanding of wasm, step 1 is impossible because there's no instruction to add a new function to the default funcref table.根据我对 wasm 的理解,步骤 1 是不可能的,因为没有将新的 function 添加到默认funcref表的指令。 Might this be subject to change in the future?这在未来可能会发生变化吗? It's a bit difficult to navigate all the wasm spec proposals so was hoping this post might get attention from someone who works on this problem to at least link to some hints on the current state of affairs.浏览所有 wasm 规范建议有点困难,因此希望这篇文章可能会引起从事此问题工作的人的注意,以至少链接到有关当前 state 事务的一些提示。

If an actual instruction in the spec is a non-starter, it seems this may be doable alternatively via a runtime API such as WASI, which could introduce an API method to modify the currently-running module in-place.如果规范中的实际指令不是启动器,则似乎可以通过运行时 API(例如 WASI)来实现,它可以引入 API 方法来就地修改当前运行的模块。 AFAICT WASI does not currently design for this nor does it have plans to. AFAICT WASI 目前没有为此设计,也没有计划。 Am I wrong about that or is there another runtime interface that does plan to do this?我错了还是有另一个运行时接口计划这样做?

WebAssembly does not support adding or removing functions (or any other elements) from running instances, and I don't know of any proposals to add such as feature. WebAssembly 不支持从正在运行的实例中添加或删除功能(或任何其他元素),而且我不知道有任何建议添加诸如功能。

To create a new function (eg when writing a JIT) you currently need to create a new module.要创建一个新的 function(例如在编写 JIT 时),您当前需要创建一个新模块。 Is there a particular reason you want to avoid this route?您是否有特殊原因要避开这条路线?

WebAssembly does support adding functions to running instances via the function table, which can be imported from the host environment. WebAssembly 确实支持通过 function 表向正在运行的实例添加功能,该表可以从主机环境中导入。
A very nontrivial example of this is that Emscripten implements dynamic linking of entirely separate WebAssembly modules with existing ones ( https://emscripten.org/docs/compiling/Dynamic-Linking.html ).一个非常重要的例子是 Emscripten 实现了完全独立的 WebAssembly 模块与现有模块的动态链接( https://emscripten.org/docs/compiling/Dynamic-Linking.html )。 In particular, Emscripten solves the problem of adding functions (with very high performance) to a running WebAssembly instance.特别是,Emscripten 解决了向正在运行的 WebAssembly 实例添加功能(具有非常高的性能)的问题。 The implementation of dlopen in Emscripten uses that the function table can be modified externally. Emscripten 中 dlopen 的实现使用 function 表可以外部修改。

If you go to https://pyodide.org/en/stable/console.html and type "import numpy", then "numpy.array(10)", then (1) all the C code of numpy gets added to the running Python WASM instance after it is instantiated, and (2) you just called one of those C functions from the Python WASM instance (the REPL is part of it). If you go to https://pyodide.org/en/stable/console.html and type "import numpy", then "numpy.array(10)", then (1) all the C code of numpy gets added to the在实例化之后运行 Python WASM 实例,并且 (2) 您刚刚从 Python 的 REPL 实例中调用了其中一个 C 函数。 This is also very fast, eg, it's not going through a slow Javascript layer.这也非常快,例如,它不会通过缓慢的 Javascript 层。

This builds on top of the existing WebAssembly spec.这建立在现有的 WebAssembly 规范之上。 It's nontrivial though.不过,这并不重要。 Eg,, a key component of making this work is the wasm32-unknown-emscripten target that's part of LLVM.例如,完成这项工作的一个关键组件是作为 LLVM 一部分的 wasm32-unknown-emscripten 目标。 which generates actual position independent code (-fPIC).它生成实际的 position 独立代码 (-fPIC)。 I don't know if there is any other WebAssembly language besides C/C++ with support for -fPIC.我不知道除了 C/C++ 之外是否还有其他支持 -fPIC 的 WebAssembly 语言。 See https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md Also, if you look at emscripten itself, eg, https://github.com/emscripten-core/emscripten/blob/main/src/library_dylink.js there's code in there to parse the wasm dynamic library, etc.请参阅https://github.com/WebAssembly/tool-conventions/blob/main/DynamicLinking.md另外,如果您查看 emscripten 本身,例如https://github.com/emscripten-core/emscripten/blobmain/ /src/library_dylink.js里面有解析wasm动态库等的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM