WaEmbedder.Memory.ETS (WaEmbedderEx v0.3.2)

Copy Markdown View Source

Page-backed linear-memory backend, a thin shim over the Erlang :wa_embedder_memory_ets implementation.

Each 64 KiB page is its own ETS entry, so a store costs O(page) rather than O(total memory). Measured against WaEmbedder.Memory.Binary on Apple silicon/OTP 27, 4-byte stores:

MemoryBinaryETS
256 KiB4.4 us1.6 us
1 MiB14.1 us1.6 us
4 MiB73.0 us1.5 us
16 MiB253.0 us1.8 us
64 MiB1070.2 us2.0 us

The cost is flat in memory size rather than linear, which is what makes it usable for a garbage-collected runtime such as QuickJS.

Use it as the :memory compile option:

:wa_embedder.compile(path, memory: WaEmbedder.Memory.ETS)

The reference is the opaque %{table: ref, pages: n, max: max} map produced by the Erlang backend; out-of-bounds access traps via :erlang.error({:wasm_trap, :memory_oob, %{addr: addr, width: width}}).

Reference semantics

The behaviour requires every callback to return a ref(), and generated code threads that return value through. Unlike WaEmbedder.Memory.Binary, which returns a fresh immutable map, this backend mutates one ETS table, so the ref returned by new/2 and the one returned by store/5 address the same table. Callers must still use the returned ref — discarding it happens to work here but is not part of the contract.

Summary

Functions

copy(ref, dst, src, n)

See :wa_embedder_memory_ets.copy/4.

fill(ref, dst, value, n)

See :wa_embedder_memory_ets.fill/4.

grow(ref, delta)

See :wa_embedder_memory_ets.grow/2.

init(ref, dst, payload, n)

See :wa_embedder_memory_ets.init/4.

load(ref, addr, width, decode)

See :wa_embedder_memory_ets.load/4.

new(min_pages, max_pages)

See :wa_embedder_memory_ets.new/2.

read(ref, offset, n)

See :wa_embedder_memory_ets.read/3.

size(ref)

See :wa_embedder_memory_ets.size/1.

store(ref, addr, width, value, value_type)

See :wa_embedder_memory_ets.store/5.

write_data(ref, offset, payload)

See :wa_embedder_memory_ets.write_data/3.