zena:memory
import {…} from 'zena:memory';
Low-level access to WebAssembly linear memory and memory allocators.
Provides Memory for reading and writing typed values at raw byte addresses,
and allocator implementations (Allocator, FreeListAllocator, BumpAllocator)
for managing linear memory buffers.
Examples ​
import { Memory, defaultAllocator } from 'zena:memory';
if (let (true, ptr) = defaultAllocator.alloc(64)) {
let mem = Memory.default;
mem.setI32(ptr, 42);
let val = mem.getI32(ptr);
defaultAllocator.free(ptr);
}
Classes
Memory
final class Memory
Represents the WASM linear memory as an array-like object. Provides typed access to memory via operator overloading.
size(): i32
Get the current size of linear memory in 64KB pages.
grow(pages: i32): i32
Grow linear memory by the specified number of pages. Returns the previous size in pages, or -1 on failure.
getU8(ptr: i32): i32
Load an unsigned byte from the given address.
setU8(ptr: i32, value: i32): void
Store a byte at the given address.
getI32(ptr: i32): i32
Load a 32-bit signed integer from the given address.
setI32(ptr: i32, value: i32): void
Store a 32-bit integer at the given address.
getI64(ptr: i32): i64
Load a 64-bit signed integer from the given address.
setI64(ptr: i32, value: i64): void
Store a 64-bit integer at the given address.
getF32(ptr: i32): f32
Load a 32-bit float from the given address.
setF32(ptr: i32, value: f32): void
Store a 32-bit float at the given address.
getF64(ptr: i32): f64
Load a 64-bit float from the given address.
setF64(ptr: i32, value: f64): void
Store a 64-bit float at the given address.
getS8(ptr: i32): i32
Load a signed byte, sign-extended to i32.
getU16(ptr: i32): i32
Load an unsigned little-endian 16-bit integer.
getS16(ptr: i32): i32
Load a signed little-endian 16-bit integer, sign-extended to i32.
setU16(ptr: i32, value: i32): void
Store the low 16 bits of value, little-endian.
copyFromBytes(ptr: i32, bytes: FixedArray<u8>, start: i32, len: i32): void
Copy len bytes of bytes, from index start, to ptr.
copyToBytes(ptr: i32, bytes: FixedArray<u8>, start: i32, len: i32): void
Copy len bytes at ptr into bytes, from index start.
bytesAt(ptr: i32, len: i32): FixedArray<u8>
The len bytes at ptr, as a fresh array.
copyToByteArray(ptr: i32, bytes: ByteArray, start: i32, len: i32): void
Copy len bytes at ptr into a ByteArray, from index start.
For building a String's backing store from memory without an
intermediate array: a String is a view over a ByteArray.
copyFromString(ptr: i32, s: String, start: i32, len: i32): void
Copy len bytes of s, from byte index start, to ptr. The
bytes are copied as the string stores them, with no re-encoding;
a caller that needs UTF-8 checks the encoding first.
copy(dst: i32, src: i32, len: i32): void
Copy len bytes from src to dst, both in linear memory. The
ranges must not overlap unless dst is below src: the copy runs
forward, so a destination above an overlapping source would read
bytes it had already overwritten. Every caller so far moves a
block into a fresh allocation.
FreeListAllocator
final class FreeListAllocator implements Allocator
A free-list allocator that supports both alloc() and free().
Uses a simple first-fit free list. Each block has an 8-byte header: [size: i32, next: i32] (next is only used when block is free)
This is the recommended allocator for general use where memory needs to be reclaimed.
new(startPtr: i32)
alloc(bytes: i32): inline (true, i32) | inline (false, _)
Allocate bytes bytes of linear memory.
allocAligned(bytes: i32, align: i32): inline (true, i32) | inline (false, _)
Allocate bytes bytes at an address that is a multiple of align,
a power of two.
Every block is already 8-aligned. For a larger alignment this takes
a block with room to spare and moves the address forward to an
aligned one at least 16 bytes in, then writes a header in front of
the new address describing the rest of the block. The part skipped
over keeps the original header, shrunk to fit, and goes onto the
free list. Both halves are ordinary blocks, so free takes the
aligned pointer like any other.
free(ptr: i32): void
Free a previously allocated pointer.
BumpAllocator
final class BumpAllocator implements Allocator
A bump-pointer allocator for arena-style memory management.
Fast allocation (just increment a pointer), but free() is a no-op. Use reset() to free all allocations at once.
To create a BumpAllocator, first allocate a region from the root allocator:
if (let (true, region) = defaultAllocator.alloc(4096)) {
let arena = new BumpAllocator(region, 4096);
if (let (true, ptr) = arena.alloc(64)) {
// use ptr
}
arena.reset(); // Reuse the arena
defaultAllocator.free(region);
}
Best for: temporary allocations with known lifetime, scratch buffers.
new(startPtr: i32, size: i32)
Create a BumpAllocator over a pre-allocated memory region.
alloc(bytes: i32): inline (true, i32) | inline (false, _)
Allocate bytes bytes. Returns (true, ptr) on success, (false, _) if exhausted.
allocAligned(bytes: i32, align: i32): inline (true, i32) | inline (false, _)
Allocate with alignment. Returns (true, ptr) on success, (false, _) if exhausted.
free(ptr: i32): void
Free is a no-op for bump allocators. Use reset() instead.
reset(): void
Reset the allocator to its initial state, allowing reuse. WARNING: This invalidates ALL previously allocated pointers!
Interfaces
Allocator
interface Allocator
Interface for linear memory allocators. Libraries should accept Allocator to allow flexible memory strategies.
Allocation methods return (true, ptr) | (false, _) to force callers
to handle allocation failures. Use pattern matching:
if (let (true, ptr) = alloc.alloc(size)) {
// use ptr
} else {
// handle out of memory
}
alloc(bytes: i32): inline (true, i32) | inline (false, _)
Allocate bytes bytes. Returns (true, ptr) on success, (false, _) on failure.
allocAligned(bytes: i32, align: i32): inline (true, i32) | inline (false, _)
Allocate bytes bytes aligned to align (must be power of 2).
free(ptr: i32): void
Free a previously allocated pointer. May be a no-op for some allocators.
Variables
defaultAllocator
let defaultAllocator: Allocator