WebAssembly is the future of Web Development. It is a low-level assembly-like language with a compact binary format that runs with near-native performance and provides languages such as C/C++ and Rust with a compilation target so that they can run on the web.
Hello, folks! your wait is over, we have come up with a new blog WebAssembly with Rust. In this blog, we will take a look at some key underlying concepts/terms which we can use in the development of WebAssembly applications with Rust. Hope you will enjoy the blog.
The Modules are the distributive, loadable, and executable unit of code in WebAssembly. At runtime, a module can be instantiated with a set of import values to produce an instance, which is an immutable tuple referencing all the states accessible to the running module. Multiple module instances can access the same shared state which is the basis for dynamic linking in WebAssembly.
WebAssembly programs are organized into modules, which are the unit of deployment, loading, and compilation. A module collects definitions for types, functions, tables, memories, and globals. In addition, it can declare imports and exports and provide initialization logic in the form of data and element segments or a start function.
(module (func (result i32) (i32.const 42) ) (export "Hello Rust" (func 0)) )
The Tables are similar to a linear memory whose elements, instead of being bytes, are opaque values of a particular table element type. This allows the table to contain values—like GC references, raw OS handles, or native pointers—that are accessed by WebAssembly code indirectly through an integer index. This feature bridges the gap between low-level, untrusted linear memory and high-level opaque handles/references at the cost of a bounds-checked table indirection.
A table is an array that lives outside of WebAssembly’s memory. The values are references to functions. Internally, these references contain memory addresses, but because they’re not inside WebAssembly’s memory, WebAssembly can’t see those addresses.
If the WebAssembly module wants to call one of these functions, it passes the index to an operation called
call_indirect. That will call the function.
The primary purpose of tables is to implement indirect function calls in C/C++ using an integer index as the pointer-to-function and the table to hold the array of indirectly-callable functions.
- Tables may only be accessed from WebAssembly code via
- The only allowed table element type is
anyfunc(function with any signature);
- Tables may not be directly mutated or resized from WebAssembly code; this can only be done through the host environment
3. Linear Memory:
A linear memory is a contiguous, byte-addressable range of memory spanning from offset
0 and extending up to varying memory sizes.
This size is always a multiple of the WebAssembly page size, which is fixed to 64KiB (though large page support may be added in an opt-in manner in the future).
The initial state of a linear memory is defined by the module’s linear memory and data sections. The memory size can be dynamically increased by the
A linear memory can be considered to be an untyped array of bytes, and it is unspecified how embedders map this array into their process’ own virtual memory.
Linear memory is sand-boxed. It does not alias other linear memories, the execution engine’s internal data structures, the execution stack, local variables, or other process memory.
Explore this blog to understand more about memory management in WebAssembly
WebAssembly has the following value types:
i32: 32-bit integer
i64: 64-bit integer
f32: 32-bit floating-point
f64: 64-bit floating-point
Note: The value types
i64 are not inherently signed or unsigned. The individual operators are responsible to interpret these types.
A module can declare a sequence of imports which are provided, at instantiation time, by the host environment. There are several kinds of imports:
- Function imports: Can be called inside the module by the
- Global imports: Can be accessed inside the module by the global operators.
- Linear memory imports: Can be accessed inside the module by the memory operators.
- Table imports: Can be accessed inside the module by call_indirect and other table operators in the future.
Imports are designed to allow modules to share code and data while still allowing separate compilation and caching.
A module can declare a sequence of exports which are returned at instantiation time to the host environment.
Each export has three fields: a name, which is required to be valid UTF-8, whose meaning is defined by the host environment, a type, indicating whether the export is a function, global, memory or table, and an index into the type’s corresponding index space.
The export component of a module defines a set of exports that become accessible to the host environment once the module has been instantiated.
Each export is labelled by a unique name. Exportable definitions are functions, tables, memories, and globals, which are referenced through a respective descriptor.
Note: I hope our blogs help you to enhance your learning. I’ll post more blogs on Rust. Stay Tuned.
If you want to read more content like this? Subscribe Rust Times Newsletter and receive insights and latest updates, bi-weekly, straight into your inbox. Subscribe Rust Times Newsletter: https://bit.ly/2Vdlld7 .