Skip to main content

Garbage Collection

WasmEdge supports the WebAssembly Garbage Collection (GC) proposal starting from version 0.14.0. This allows high-level languages like Kotlin, Dart, and OCaml to compile to WebAssembly without bundling their own garbage collector, resulting in smaller binaries and better runtime performance.

What is Wasm GC?​

Normally, WebAssembly manages memory manually — programs allocate and free memory themselves using linear memory. The GC proposal adds first-class garbage-collected types: structs (fixed heterogeneous fields) and arrays (homogeneous elements), both allocated on the heap and automatically reclaimed when no longer reachable.

This is enabled by default in WasmEdge since 0.16.0. For WasmEdge 0.14.x–0.15.x, enable it explicitly with the (deprecated) --enable-gc flag; you can disable GC with --disable-gc when needed.

Prerequisites​

Install wasm-tools on Linux (x86_64):

curl -LO https://github.com/bytecodealliance/wasm-tools/releases/download/v1.262.0/wasm-tools-1.262.0-x86_64-linux.tar.gz
tar -xzf wasm-tools-1.262.0-x86_64-linux.tar.gz
sudo install wasm-tools-1.262.0-x86_64-linux/wasm-tools /usr/local/bin/wasm-tools

Or on macOS:

brew install wasm-tools

For other platforms, see the wasm-tools installation instructions.

Example: Working with Structs​

The following WAT (WebAssembly Text Format) example defines a $point struct with two i32 fields, allocates one, sets a field, and returns a value from it.

Create a file called point.wat:

(module
(type $point (struct (field $x (mut i32)) (field $y (mut i32))))

(func (export "make_point") (result i32)
(local $p (ref $point))
;; Allocate a new $point struct with x=10, y=20
(local.set $p
(struct.new $point (i32.const 10) (i32.const 20))
)
;; Update x to 99
(struct.set $point $x (local.get $p) (i32.const 99))
;; Return the value of x
(struct.get $point $x (local.get $p))
)
)

Compile it to a .wasm binary:

wasm-tools parse point.wat -o point.wasm

Run it with WasmEdge:

wasmedge --reactor point.wasm make_point

Expected output:

99

Example: Working with Arrays​

The following example creates a GC-managed array of i32 values, fills it with a value, and reads back an element.

Create a file called array.wat:

(module
(type $int_array (array (mut i32)))

(func (export "array_example") (result i32)
(local $a (ref $int_array))
;; Allocate an array of length 5, initialized to 0
(local.set $a
(array.new_default $int_array (i32.const 5))
)
;; Set element at index 2 to 42
(array.set $int_array (local.get $a) (i32.const 2) (i32.const 42))
;; Return element at index 2
(array.get $int_array (local.get $a) (i32.const 2))
)
)

Compile and run:

wasm-tools parse array.wat -o array.wasm
wasmedge --reactor array.wasm array_example

Expected output:

42

Disabling GC​

If you need to run a Wasm module without GC support (for example, to test compatibility), pass the --disable-gc flag:

wasmedge --disable-gc your_module.wasm

C API​

To configure GC support programmatically via the WasmEdge C API, use the WasmEdge_Proposal_GC enumeration value:

WasmEdge_ConfigureContext *ConfCxt = WasmEdge_ConfigureCreate();
// WasmEdge 0.16.0+ enables GC by default; to disable it:
WasmEdge_ConfigureRemoveProposal(ConfCxt, WasmEdge_Proposal_GC);
// WasmEdge 0.14.x–0.15.x has GC off by default; to enable it instead:
// WasmEdge_ConfigureAddProposal(ConfCxt, WasmEdge_Proposal_GC);

Language Support​

Languages that compile to Wasm GC and can run on WasmEdge include:

  • Kotlin/Wasm — via the Kotlin compiler's wasmGc target
  • Dart — via dart compile wasm
  • OCaml — via the wasm_of_ocaml compiler

For language-specific guides, refer to each toolchain's documentation on enabling WebAssembly GC support in its Wasm backend.