Bulk Memory, Multi-Value and Reference Types
21.1 Bulk Memory Operations
Much faster than byte loops. Compilers emit these for memset/memcpy (-mbulk-memory, the default in modern toolchains).
(module
(memory 1)
(data $greeting "Hello") ;; passive segment (not copied at instantiation)
(func (export "init")
(memory.init $greeting (i32.const 100) (i32.const 0) (i32.const 5)) ;; dest, src offset, len
(data.drop $greeting)) ;; free the segment
(func (export "zero") (param $ptr i32) (param $len i32)
(memory.fill (local.get $ptr) (i32.const 0) (local.get $len))) ;; like memset
(func (export "copy") (param $dst i32) (param $src i32) (param $len i32)
(memory.copy (local.get $dst) (local.get $src) (local.get $len)))) ;; like memmove21.2 Multi-Value
Functions and blocks can return multiple values, which avoids memory round trips for tuples (e.g., Rust returning (u32, u32), divmod).
21.3 Reference Types (externref, funcref)
Enables holding JS objects without integer-handle tables in glue code. wasm-bindgen uses externref when the reference-types feature is enabled.
(module
(import "js" "describe" (func $describe (param externref)))
(table $objects 10 externref)
(func (export "store") (param $i i32) (param $obj externref)
(table.set $objects (local.get $i) (local.get $obj)))
(func (export "show") (param $i i32)
(call $describe (table.get $objects (local.get $i))))
(func (export "isNull") (param $r externref) (result i32)
(ref.is_null (local.get $r))))instance.exports.store(0, document.body); // any JS value, held opaquely
instance.exports.show(0);