zig-gc

API reference

On this page 159

Every declaration below is extracted from zig-gc's source, with the doc comments as written there. A declaration listed without prose is public but undocumented in the source.

Root

Heap

const Heap = @import("heap.zig").Heap

CollectionPhaseBoundary

const CollectionPhaseBoundary = @import("heap.zig").CollectionPhaseBoundary

InteriorOwnership

const InteriorOwnership = @import("heap.zig").InteriorOwnership

RelocationRecord

const RelocationRecord = @import("heap.zig").RelocationRecord

RelocationState

const RelocationState = @import("heap.zig").RelocationState

RelocationVisitor

const RelocationVisitor = @import("heap.zig").RelocationVisitor

StableCellId

const StableCellId = @import("heap.zig").StableCellId

Heap

CollectionPhaseBoundary

const CollectionPhaseBoundary = enum

Semantic collection boundaries for opt-in embedder profiling. The generic heap deliberately owns no clock or counters; bindings that omit the hook pay no runtime cost. prepare_begin is emitted only after a collection is known to run, post_sweep_end follows the optional afterSweep hook, and abort closes an attempt that deliberately skipped weak clearing and sweep.

InteriorOwnership

const InteriorOwnership = union(enum)

Optional binding result for conservative interior-address classification. allocation is the exact cell allocation base (the header address), while owned_empty means the address lies in owned storage but cannot name an issued allocation. outside permits the collector's generic fallback unless the binding separately proves that every cell uses its owned storage.

StableCellId

const StableCellId = enum(u64)

Process-unique, address-independent identity for one collector cell. IDs are non-zero, never recycled, and remain attached to a cell when compaction relocates its storage. Embedders may use them for diagnostics such as heap snapshots, but must not expose them as mutable language state.

init

fn init(raw: u64) StableCellId

RelocationState

const RelocationState = enum

RelocationRecord

fn RelocationRecord(comptime Kind: type) type

RelocationVisitor

fn RelocationVisitor(comptime Kind: type) type

Infallible old→new resolver handed to binding rewrite hooks after every destination has been reserved. Cells absent from the plan are pinned and retain their address. Dead weak targets have already been cleared before relocation begins, so every non-null weak target follows the same mapping.

resolve

fn resolve(self: *const @This(), old_payload: *anyopaque) *anyopaque

moved

fn moved(self: *const @This(), old_payload: *anyopaque) bool

stableId

fn stableId(self: *const @This(), old_payload: *anyopaque) ?StableCellId

Heap

fn Heap(comptime Binding: type) type

Kind

const Kind = Binding.Kind

CellMetadata

const CellMetadata = struct

RelocationRecordType

const RelocationRecordType = RelocationRecord(Kind)

RelocationVisitorType

const RelocationVisitorType = RelocationVisitor(Kind)

min_nursery_threshold_bytes

const min_nursery_threshold_bytes: usize = 4 * 1024 * 1024

default_nursery_threshold_bytes

const default_nursery_threshold_bytes: usize = 4 * 1024 * 1024

default_tenuring_age

const default_tenuring_age: u8 = 1
const Header = struct

cellAllocationBytes

fn cellAllocationBytes(comptime T: type) usize

Exact backing allocation size for a cell payload type. Embedders that claim all cells use owned storage use this in an exhaustive comptime proof over their cell taxonomy.

Visitor

const Visitor = struct

mark

fn mark(v: *Visitor, cell: ?*anyopaque) void

Mark a strong reference. Null-safe and idempotent (tri-color: white→grey on first sight, pushed once). The white→grey claim is atomic under a concurrent mark so the marker and a mutator's writeBarrier never both push the same cell.

markProperty

fn markProperty(v: *Visitor, name: []const u8, cell: ?*anyopaque) void

Labeled edge variants let bindings retain precise provenance in corruption diagnostics without adding work to successful marks.

markIndex

fn markIndex(v: *Visitor, index: usize, cell: ?*anyopaque) void

markVariable

fn markVariable(v: *Visitor, name: []const u8, cell: ?*anyopaque) void

markInternal

fn markInternal(v: *Visitor, name: []const u8, cell: ?*anyopaque) void

isManaged

fn isManaged(v: *Visitor, cell: ?*anyopaque) bool

Whether cell is one of this heap's managed payloads. Bindings use this before marking legacy/embedder pointers that may still point outside the GC heap. Unlike mark, this predicate must tolerate stale or wild values: root tracers often use it specifically at mixed ownership boundaries, where a header peek would turn a bad legacy pointer into a collector crash. So this walks the heap's live-cell list for an exact payload match instead of reading from the candidate address. The walk is intentionally paid only by "maybe managed" compatibility edges; precise edges should call mark directly.

isMarked

fn isMarked(v: *Visitor, cell: ?*anyopaque) bool

Whether a cell is already black/grey in the current collection. Used by ephemeron tables: if the key is live, the value is a strong edge; if the key stays white, the entry is weak.

markConservativeWord

fn markConservativeWord(v: *Visitor, word: usize) void

Conservatively mark a machine word if it points at the payload of a managed cell. This is intentionally opt-in: precise embedders should keep using mark, while runtimes that need to root native stacks can scan a stack/register spill range without teaching the collector about their frame layout.

markConservativeWords

fn markConservativeWords(v: *Visitor, start: [*]const usize, words: usize) void

Scan a word-aligned range, inclusive of start and spanning words machine words. The caller owns choosing safe stack or register-spill bounds for its platform.

concurrent

fn concurrent(v: *Visitor) bool

Whether this trace is running on the marker thread concurrently with live mutators (M3). Bindings whose cells have internally mutable storage (a growable slot/element vector behind a lock) must, when this is true, read that storage under the same lock the mutator takes — otherwise the marker's read races a mutator's append/realloc. False under stop-the-world (M1) and GIL-held incremental (M2) marking, where the world is quiescent during the read, so the binding can skip the lock on those paths.

deferToFinish

fn deferToFinish(v: *Visitor, cell: *anyopaque) void

Defer this (already-marked) cell's tracing to the world-stopped finishConcurrentMark. For cells whose mutable storage is too entangled to read safely mid-mark (e.g. a generator whose exec is the live VM stack, or an iterator helper whose fields update around JS callbacks): the binding calls this from trace when concurrent(), so the cell survives this cycle (it is marked) but its children are discovered at finish, when the mutator is quiescent and the storage is stable. A no-op outside a concurrent mark (the caller should just trace normally then).

markWeak

fn markWeak(v: *Visitor, slot: *?*anyopaque) void

Register a weak slot. After marking completes, if its target stayed white the slot is set to null (the cell is dying).

markWeakAtomic

fn markWeakAtomic(v: *Visitor, slot: *std.atomic.Value(?*anyopaque)) void

Register an externally synchronized weak slot. Clearing uses a CAS so a concurrent embedder clear cannot race a plain store and a future retargeting API cannot lose a newly published target.

init

fn init(backing: std.mem.Allocator, ctx: *Binding) Self

setAuxAllocator

fn setAuxAllocator(self: *Self, aux: std.mem.Allocator) void

Install a thread-safe scratch allocator for concurrent marking (M3). Must be called right after init, before any allocation, since mark_stack/barrier_buf must be freed with the same allocator they were grown with. A no-op conceptually for M1/M2 (leave it as backing).

setParallel

fn setParallel(self: *Self, parallel: bool) void

Enable multi-mutator allocation (the post-GIL model): create's shared-state bookkeeping runs under alloc_lock. backing must be thread-safe. Leave off (default) for the single-GIL'd-mutator model so allocation pays no lock.

setConcurrentMarkerMetadata

fn setConcurrentMarkerMetadata(self: *Self, enabled: bool) void

Serialize allocation metadata against a single dedicated marker thread. Use this for concurrent marking without enabling the multi-mutator parallel collector protocol.

setNurseryEnabled

fn setNurseryEnabled(self: *Self, enabled: bool) void

Enable the nursery. New cells start at age zero; a minor collection reclaims unreachable young cells, advances live survivors, and tenures cells that reach tenuring_age. Existing cells stay old, so enabling this after heap initialization is safe. Disabling with a pending nursery tenures that entire young prefix without collecting: later old allocations can therefore never split the prefix before a re-enable.

setMovingNurseryEnabled

fn setMovingNurseryEnabled(self: *Self, enabled: bool) void

Move every live young survivor after weak processing and sweep. Embedders must still open their relocation/root-rewrite token at the stop window; enabling the policy alone never makes an unsafe stack movable.

movingNurseryEnabled

fn movingNurseryEnabled(self: *const Self) bool

setNurseryTenuringAge

fn setNurseryTenuringAge(self: *Self, age: u8) void

Select how many successful minor collections a young cell must survive before promotion. One preserves the original single-cycle nursery policy; larger values retain a measured multi-age nursery.

Accounting

const Accounting = struct

Race-safe accounting snapshot for embedders that expose heap usage or collection telemetry. live_bytes includes the collector header and payload allocation for every currently live cell. The last-full value changes only after a completed full sweep, never after a nursery-only cycle or an in-progress concurrent mark.

CompactionStatus

const CompactionStatus = enum

CompactionResult

const CompactionResult = struct

accounting

fn accounting(self: *Self) Accounting

cellMetadata

fn cellMetadata(self: *Self, payload: ?*anyopaque) ?CellMetadata

Return immutable diagnostics metadata for a live cell. The embedder must call this at a heap-quiescent boundary, so collection cannot reclaim the returned cell between lookup and the metadata reads. Null and unmanaged/stale payloads return null.

isLive

fn isLive(self: *Self, p: ?*anyopaque) bool

Whether p is a live (marked) cell — O(1). p must be null or a pointer to a cell allocated by this heap. This is the read a binding uses for isMarked-based weak clearing: deciding a weak key's / finalizer target's liveness in the world-stopped finish pass by its mark bit, instead of pre-registering an interior &slot weak pointer that a concurrent mutator append could dangle by reallocating the buffer it points into. Call only with marks still valid (before sweep).

create

fn create(self: *Self, comptime T: type, kind: Kind) !*T

Allocate a GC-managed cell of type T tagged kind. The returned pointer is uninitialized payload; the caller writes it before the next safepoint (so a collection never traces a half-built cell).

createBatch

fn createBatch(self: *Self, comptime T: type, kind: Kind, out: []*T) !usize

Allocate several same-kind cells privately, then publish the successfully allocated prefix under one metadata lock. Returning a short prefix defers recovery/OOM until the caller has initialized and consumed those cells, preserving sequential allocation failure ordering. Every returned payload is uninitialized and must be fully initialized before the caller's next safepoint, just like create.

maybeCollect

fn maybeCollect(self: *Self) void

Collect if the heap has grown past the threshold. Call at safepoints (the engine's (steps & 1023) checkpoints) and after large allocs.

writeBarrier

fn writeBarrier(self: *Self, cell: ?*anyopaque) void

Dijkstra insertion write barrier. The embedder calls this whenever it stores a reference to cell into a heap object during an incremental mark: it shades cell grey so a reference newly hidden behind an already-black object is never missed (the black→white invariant). A no-op when not marking, when cell is null, or when cell is not a managed payload (the embedder may store non-cell pointers) — so it is cheap and safe to call broadly. Idempotent (already-grey/black: skip).

writeBarrierFrom

fn writeBarrierFrom(self: *Self, owner: ?*anyopaque, cell: ?*anyopaque) void

Owner-aware insertion barrier. In nursery mode an old owner is remembered when it receives a young child, so minor collection only rescans dirty old containers. The incremental/full barrier remains identical to writeBarrier.

writeBarrierFromManaged

fn writeBarrierFromManaged(self: *Self, owner: *anyopaque, cell: *anyopaque) void

Fast owner-aware barrier for exact live managed payloads allocated by this heap. Unlike writeBarrierFrom, this deliberately does not classify arbitrary pointers through the live-payload index. The caller must provide non-null payload starts from this heap; use the tolerant barrier whenever either pointer may be external or stale.

writeBarrierWeak

fn writeBarrierWeak(self: *Self, owner: ?*anyopaque) void

Remember an old container whose weak slots changed. This does not mark the weak target; it merely ensures minor GC revisits the container to apply normal weak/ephemeron semantics.

markWorkPublicationFailed

fn markWorkPublicationFailed(self: *const Self) bool

startMarking

fn startMarking(self: *Self) void

Begin an incremental mark: whiten all cells and grey the roots. The mutator then runs between markSteps with the writeBarrier active.

markStep

fn markStep(self: *Self, budget: usize) bool

Process up to budget grey cells (0 = unbounded). Returns true when the mark stack is empty (the grey set is drained for now). Because the barrier keeps shading during mutation, "drained" is not final until finishMarking re-checks under a stop.

finishMarking

fn finishMarking(self: *Self) void

Finish an incremental mark (stop-the-world tail): re-scan the roots, drain the grey set, run the ephemeron fixpoint and weak processing, then sweep. The root re-scan closes the one gap the heap-store insertion barrier doesn't: a reachable-but-white cell the mutator moved onto a root (an operand stack, a native frame, the microtask queue) after startMarking snapshotted them. Heap→heap moves are covered by the barrier; root moves are covered here. (For a stop-the-world collect() no mutation happened, so this re-scan only re-touches already-marked roots — cheap and harmless.)

collect

fn collect(self: *Self) void

A full stop-the-world cycle: mark from roots, clear dead weak edges, sweep (finalizing) the white cells. Equivalent to startMarking + drain + finishMarking, kept as the default.

collectAndCompact

fn collectAndCompact(self: *Self) CompactionResult

Run a full collection and then compact every live cell accepted by the binding. Destination reservation is failure-atomic: allocation and the old→new index complete before the first old byte, root, edge, publication bit, or heap index is changed. Rewrite/commit hooks are therefore infallible and execute only with a complete plan.

collectYoung

fn collectYoung(self: *Self) void

collectYoungAndCompact

fn collectYoungAndCompact(self: *Self) CompactionResult

Run the same exact minor trace/weak/sweep contract, then relocate every survivor (including cells promoted by this cycle). Destination reservation completes before roots or graph bytes change.

beginConcurrentMark

fn beginConcurrentMark(self: *Self) void

Begin a concurrent mark. Call with the world stopped (no mutator running): whitens all cells and greys the roots into mark_stack, then flips concurrent on so mutators route through barrier_buf.

beginConcurrentMarkParallel

fn beginConcurrentMarkParallel(self: *Self) void

Begin a concurrent mark for the parallel (multi-mutator, GIL-free) model: peer mutators keep allocating and mutating on other threads while this runs. Unlike beginConcurrentMark, the world is NOT stopped, so:

  • The whiten pass + state reset run under alloc_lock, the same leaf lock create takes, so the O(n) all-list walk and the born-grey mark-bit set can't race a peer's prepend. alloc_lock is a leaf (never held across a safepoint or a per-structure lock), so guarding the walk with it cannot deadlock a mutator that is parked or spinning for an object lock. The whiten stores to marked are atomic because alloc_lock does NOT serialize the barrier path: a peer still finishing a store from the previous cycle (it read marking true before the prior finish cleared it) reaches claimMark, whose CAS atomically touches marked without alloc_lock. That CAS is always a benign no-op here — its target was reachable-and-marked last cycle, so the strong CAS fails and writeBarrier returns before mutating any list (a successful CAS would mean a swept-garbage target, which the terminal root handshake already rules out). Atomic-vs-atomic is race-free; the new cycle's happens-before is the marking=true release below.
  • marking+concurrent are published while still holding alloc_lock, so no cell can be prepended between "whitened" and "barrier armed": a create that wins the lock after us already sees marking true and is born grey.
  • After arming the barrier, Binding.traceRoots greys the embedder's roots. The embedder is responsible for making that trace touch only roots that are safe to read while peers run (its global/realm state, parked-peer stacks, the collector's own stack) and for layering each running peer's own roots in via a safepoint handshake (src/root_handshake.zig) — a running peer's live VM/native stack can't be read by another thread. Peers' concurrent stores shade through barrier_buf and their allocations are born grey, so nothing reachable is missed. Requires parallel.

concurrentMarkRound

fn concurrentMarkRound(self: *Self) bool

One marker-thread round: trace everything currently grey, then fold in whatever the mutator handed off. Returns true when both the local stack and the hand-off buffer were empty this round (a quiescent point — not final until the world is stopped for finishConcurrentMark).

finishConcurrentMark

fn finishConcurrentMark(self: *Self) void

Finish a concurrent mark (call with the world stopped): fold in any remaining hand-off, re-scan roots, drain, run the ephemeron/weak pass, and sweep. After this concurrent/marking are off.

bornPendingLen

fn bornPendingLen(self: *Self) usize

Pending mutator-allocated cells not yet folded into the mark (M3 parallel). The driver watches this for stability across two all-published handshake rounds: a stable count means no peer is mid-allocation, so every born cell's payload is fully initialized and safe to fold at finishConcurrentMarkParallel.

deferredPendingLen

fn deferredPendingLen(self: *Self) usize

Cells whose tracing the marker deferred to finish (generators / iterator helpers whose mutable exec/inner can't be read while the owning mutator runs). The parallel driver refuses to finish (aborts) while this is non-empty, because a running peer's deferred cell can't be traced soundly — only a world-stopped or quiescent finish can.

finishConcurrentMarkParallel

fn finishConcurrentMarkParallel(self: *Self) bool

Finish a concurrent mark in the PARALLEL model — peers keep running, no stop-the-world. The caller (the engine's mid-script driver) must have confirmed via the root handshake that every peer published the current generation, that born_concurrent is stable (no peer mid-allocation, so every born payload is initialized), and that deferred_trace is empty. Given that, marking has reached closure over all live roots, and any store a peer makes from here can only shade a cell reachable from its already-published (and traced) roots — i.e. an already-marked cell — so it is sound to drain and sweep without freezing the world. Claims stay atomic until the final marking=false; the sweep runs under alloc_lock (sweepPhase). Returns true if it swept, false if it had to bail (a peer allocated during the finish, so newly-born cells would be untraced and their un-barriered creation-time references could be missed); on false the caller aborts (abortConcurrentMarkParallel), freeing nothing.

shouldCollect

fn shouldCollect(self: *Self) bool

Whether live bytes have crossed the collection threshold, read under alloc_lock in parallel mode so a mid-script collector's safepoint check doesn't race a peer's create updating bytes_live.

shouldCollectOld

fn shouldCollectOld(self: *Self) bool

Whether tenured bytes alone have crossed the full-heap threshold. Generational embedders use this at quiescent boundaries so a large young batch receives a minor collection before it can force a full trace. Mid-script collectors that cannot run minor GC should continue using shouldCollect() over total bytes.

shouldCollectYoung

fn shouldCollectYoung(self: *Self) bool

Whether the nursery has reached its collection threshold, or a remembered-set allocation failure requires the next nursery request to fall back to a full collection.

abortConcurrentMarkParallel

fn abortConcurrentMarkParallel(self: *Self) void

Abort an in-progress parallel concurrent mark after the embedding's terminal handshake could not reach a stable finish. Frees no cells.

deinit

fn deinit(self: *Self) void

Free every remaining cell (finalizing each) and the internal lists. The embedder calls this at context teardown — equivalent to the old arena deinit, but finalizers run.

deinitRetainingCellStorage

fn deinitRetainingCellStorage(self: *Self) void

Finalize every remaining cell and release collector side buffers, but do not return individual cell allocations to backing. Use only when the embedder owns those allocations through a slab/arena that it will reclaim wholesale immediately afterward. Cell finalizers still run in full, so side storage and host resources are released normally.

Kind

const Kind = enum

traceRoots

fn traceRoots(self: *TestRT, v: anytype) void

afterWeakRoots

fn afterWeakRoots(self: *TestRT) void

afterSweep

fn afterSweep(self: *TestRT) void

collectionPhaseBoundary

fn collectionPhaseBoundary(self: *TestRT, boundary: CollectionPhaseBoundary) void

trace

fn trace(cell: *anyopaque, kind: Kind, v: anytype) void

canRelocate

fn canRelocate(_: *TestRT, cell: *anyopaque, kind: Kind) bool

canRelocateYoung

fn canRelocateYoung(_: *TestRT, _: *anyopaque, _: Kind) bool

relocateRoots

fn relocateRoots(self: *TestRT, v: anytype) void

relocateCell

fn relocateCell(_: *TestRT, cell: *anyopaque, kind: Kind, v: anytype) void

verifyRelocationRoots

fn verifyRelocationRoots(self: *TestRT, v: anytype) void

verifyRelocationCell

fn verifyRelocationCell(self: *TestRT, cell: *anyopaque, kind: Kind, v: anytype) void

reserveRelocationCell

fn reserveRelocationCell(self: *TestRT, total: usize) ?*anyopaque

releaseRelocationReservation

fn releaseRelocationReservation(self: *TestRT, allocation: *anyopaque, total: usize) void

commitRelocationCell

fn commitRelocationCell(self: *TestRT, old: *anyopaque, _: *anyopaque, total: usize) void

finalize

fn finalize(self: *TestRT, cell: *anyopaque, kind: Kind) void

Kind

const Kind = enum

allocateCellBatch

fn allocateCellBatch(self: *BatchAllocTestRT, total: usize, out: []*anyopaque) usize

publishCellAllocationBatch

fn publishCellAllocationBatch(self: *BatchAllocTestRT, payloads: []*anyopaque, _: usize, payload_offset: usize) void

allCellsUseOwnedStorage

fn allCellsUseOwnedStorage(_: *BatchAllocTestRT) bool

traceRoots

fn traceRoots(_: *BatchAllocTestRT, _: anytype) void

trace

fn trace(_: *anyopaque, _: Kind, _: anytype) void

finalize

fn finalize(_: *BatchAllocTestRT, _: *anyopaque, _: Kind) void

Kind

const Kind = enum

Iterator

const Iterator = struct

next

fn next(self: *Iterator) ?*anyopaque

ownedCellIterator

fn ownedCellIterator(self: *ShardedBatchTestRT) Iterator

allCellsUseOwnedStorage

fn allCellsUseOwnedStorage(_: *ShardedBatchTestRT) bool

usesOwnedCellStorage

fn usesOwnedCellStorage(_: *ShardedBatchTestRT, _: usize) bool

allocateCellBatch

fn allocateCellBatch(self: *ShardedBatchTestRT, total: usize, out: []*anyopaque) usize

publishCellAllocation

fn publishCellAllocation(self: *ShardedBatchTestRT, allocation: *anyopaque, _: usize) void

publishCellAllocationBatch

fn publishCellAllocationBatch(self: *ShardedBatchTestRT, payloads: []*anyopaque, _: usize, payload_offset: usize) void

unpublishCellAllocation

fn unpublishCellAllocation(self: *ShardedBatchTestRT, allocation: *anyopaque, _: usize) void

ownsCellAllocation

fn ownsCellAllocation(self: *ShardedBatchTestRT, allocation: *anyopaque) bool

freeCellStorageBatch

fn freeCellStorageBatch(_: *ShardedBatchTestRT, total: usize, allocations: []*anyopaque) void

traceRoots

fn traceRoots(_: *ShardedBatchTestRT, _: anytype) void

trace

fn trace(_: *anyopaque, _: Kind, _: anytype) void

finalize

fn finalize(_: *ShardedBatchTestRT, _: *anyopaque, _: Kind) void

Kind

const Kind = enum

traceRoots

fn traceRoots(_: *SweepBatchTestRT, _: anytype) void

trace

fn trace(_: *anyopaque, _: Kind, _: anytype) void

finalize

fn finalize(_: *SweepBatchTestRT, _: *anyopaque, _: Kind) void

freeCellStorageBatch

fn freeCellStorageBatch(self: *SweepBatchTestRT, total: usize, allocations: []*anyopaque) void

Kind

const Kind = enum

traceRoots

fn traceRoots(self: *OwnedCellTestRT, v: anytype) void

trace

fn trace(_: *anyopaque, _: Kind, _: anytype) void

finalize

fn finalize(self: *OwnedCellTestRT, _: *anyopaque, _: Kind) void

publishCellAllocation

fn publishCellAllocation(self: *OwnedCellTestRT, allocation: *anyopaque, _: usize) void

unpublishCellAllocation

fn unpublishCellAllocation(self: *OwnedCellTestRT, allocation: *anyopaque, _: usize) void

usesOwnedCellStorage

fn usesOwnedCellStorage(_: *OwnedCellTestRT, _: usize) bool

ownsCellAllocation

fn ownsCellAllocation(self: *OwnedCellTestRT, allocation: *anyopaque) bool

classifyConservativeInterior

fn classifyConservativeInterior(self: *OwnedCellTestRT, address: usize) InteriorOwnership

allCellsUseOwnedStorage

fn allCellsUseOwnedStorage(_: *OwnedCellTestRT) bool

Kind

const Kind = enum

Iterator

const Iterator = struct

next

fn next(self: *Iterator) ?*anyopaque

ownedCellIterator

fn ownedCellIterator(self: *OwnedIterationTestRT) Iterator

allCellsUseOwnedStorage

fn allCellsUseOwnedStorage(_: *OwnedIterationTestRT) bool

usesOwnedCellStorage

fn usesOwnedCellStorage(_: *OwnedIterationTestRT, _: usize) bool

ownsCellAllocation

fn ownsCellAllocation(self: *OwnedIterationTestRT, allocation: *anyopaque) bool

publishCellAllocation

fn publishCellAllocation(self: *OwnedIterationTestRT, allocation: *anyopaque, _: usize) void

unpublishCellAllocation

fn unpublishCellAllocation(self: *OwnedIterationTestRT, allocation: *anyopaque, _: usize) void

traceRoots

fn traceRoots(self: *OwnedIterationTestRT, v: anytype) void

trace

fn trace(cell: *anyopaque, _: Kind, v: anytype) void

traceOldOnMinor

fn traceOldOnMinor(_: Kind) bool

finalize

fn finalize(self: *OwnedIterationTestRT, cell: *anyopaque, _: Kind) void

Kind

const Kind = enum

hasWeakWork

fn hasWeakWork(self: *EphRT) bool

traceRoots

fn traceRoots(self: *EphRT, v: anytype) void

traceOldOnMinor

fn traceOldOnMinor(kind: Kind) bool

trace

fn trace(cell: *anyopaque, kind: Kind, v: anytype) void

traceEphemeron

fn traceEphemeron(self: *EphRT, cell: *anyopaque, kind: Kind, v: anytype) void

afterWeak

fn afterWeak(self: *EphRT, cell: *anyopaque, kind: Kind) void

finalize

fn finalize(self: *EphRT, cell: *anyopaque, kind: Kind) void