Allocator entry points, raw memory operations, cached small-block allocation, and heap-usage accounting.


Use

"memory" use exposes the raw C bindings, cached allocation helpers, public allocator entry points, and heap-usage query.


Allocation model

SYNCHRONIZED

(-- cond) Reports whether allocation helpers synchronize access for concurrent use.
  • Defaults to FALSE.

Known issue: enabling SL_MEMORY_SYNCHRONIZED currently fails compilation because the memory module requests the unavailable atomic name MONOTONIC. The current default cache path is not synchronized; do not use it concurrently without external synchronization.

SL_MEMORY_MAX_CACHED_SIZE

(-- size) Provides the greatest allocation size handled by the cached helpers.
  • If the build does not define this setting, the module uses 0x40000nx.
  • Use a Natx limit of zero to disable caching, or a limit at least Natx storageSize. The head table needs (limit + 1) * Natx storageSize bytes; choose a representable, allocatable size.

haveSLMemoryMaxCachedSize

(-- cond) Reports whether SL_MEMORY_MAX_CACHED_SIZE is available. After this module supplies the default, the result is also TRUE; it does not distinguish the default from a build-supplied setting.

debugMemory

(-- cond) Reports whether the debug allocation wrappers are enabled.
  • Enable the debug wrappers with -D DEBUG_MEMORY=TRUE. The setting must evaluate to a known Cond; FALSE disables the wrappers.

memoryQueues

(-- address) Returns an immutable view of the Natx address of the cache-head table. This is public allocator bookkeeping; callers must not overwrite the table or change its head links.

Returned blocks are aligned for pointer-sized storage and are not zero-initialized. Callers must initialize contents when required. Allocation exhaustion has no separate error result in these wrappers.

Cached/public allocation requests require nonzero sizes, except for explicitly documented null-pointer branches. Checked violations report Invalid allocation size. Known violations can fail compilation; run-time assertions require DEBUG. Disabling checks does not make an invalid request supported.


Public allocation entry points

mplMalloc

(size -- ptr) Allocates one mutable block through the public memory wrapper.
  • With debug metrics enabled, the allocation count, sizes, and checksum are updated.
  • The returned pointer remains valid until it is passed to mplFree or mplRealloc; a null pointer denotes allocation failure.

mplRealloc

(newSize oldSize ptr -- newPtr) Allocates a resized block, copies the shared prefix, and releases the old block.
  • Without debug wrappers, this is fastReallocate: supply a live allocation and nonzero old/new sizes. With debug wrappers enabled, a zero input address instead allocates newSize bytes and ignores oldSize.
  • The copied count is min(oldSize newSize). The old pointer is invalid after a successful call; the returned mutable pointer remains valid until the next release or resize.
  • These helpers allocate a new block and release the old one, rather than calling native realloc. Known issue: the copy path does not check allocation failure before using the new address. Do not rely on a safe null result or preservation of the old block on exhaustion.

mplFree

(size ptr --) Releases a block through the public memory wrapper.
  • Supply the allocation size and address. The debug wrapper treats address zero as a no-op; do not rely on that behavior when debug wrappers are disabled.
  • The released pointer is invalid after the call.

Example: public allocation helpers

"control" use
"memory"  use

{} () {} [
  p0: 4nx mplMalloc;
  4nx 65 p0 memset drop
  p1: 8nx 4nx p0 mplRealloc;
  p1 Nat8 addressToReference new printStack _:;
  8nx p1 mplFree
] "main" exportFunction

Expected Output During Compilation

Nat8

Runtime example

"String"  use
"control" use
"memory"  use

{} Int32 {} [
  p0: 4nx mplMalloc;
  4nx 65 p0 memset drop
  p1: 8nx 4nx p0 mplRealloc;
  p1 Nat8 addressToReference new 65n8 = print
  LF print
  8nx p1 mplFree
  0
] "main" exportFunction

Expected Output

TRUE

Raw memory functions

Addresses, byte counts, and allocation sizes are Natx. memset's fill value and memcmp's result are Int32.

malloc

(size -- ptr) Allocates a mutable block of size bytes.

realloc

(size ptr -- newPtr) Resizes ptr and returns a mutable pointer to the resized block.
  • For a nonzero requested size, a zero result indicates failure and leaves the original allocation valid. Do not overwrite the only saved old address before checking the result.

free

(ptr --) Releases ptr; ptr is invalid after the call.
  • Address zero is accepted. A nonzero address must be a live compatible native allocation and must not already have been freed.

memcpy

(num src dst -- result) Copies num bytes from src to dst; overlapping ranges are invalid.

memmove

(num src dst -- result) Copies num bytes from src to dst with overlap handling.

memcmp

(num memptr2 memptr1 -- result) Compares num bytes at two addresses and returns the C comparison result.
  • Returns an Int32 less than, equal to, or greater than zero according to the byte comparison. Only the sign is the ordering result.

memset

(num value dst -- result) Fills num bytes at dst with the low byte of value and returns the mutable dst pointer.

memcpy and memmove return the destination address. Supply valid ranges of at least num bytes; memcpy requires nonoverlapping ranges, while memmove permits overlap.

Raw allocation failure is represented by a null pointer; these bindings do not create an error record. A zero-size raw allocation follows the platform C allocator; it is not subject to the cached/public helper check. Pointer results designate mutable storage and remain valid only under the caller's allocation lifetime.

Pair raw malloc/realloc blocks with free. Pair cached/public blocks with their corresponding size-aware release operation, preserving the allocation size. Do not invent a different size or mix allocator families. Cached releases may retain storage rather than return it to the C allocator.


Cached allocation helpers

fastAllocate

(size -- ptr) Allocates a block for size bytes. Requests above SL_MEMORY_MAX_CACHED_SIZE use the native allocator directly. Cached requests use the exact byte count as their class, except that counts below Natx storageSize share the pointer-sized class. Freed cached blocks are retained for reuse; their contents are not zeroed.
  • The returned pointer remains valid until fastDeallocate or fastReallocate releases it.

fastDeallocate

(size ptr --) Releases a block previously returned by fastAllocate or fastReallocate.
  • The caller must supply the original nonzero size; the pointer is invalid after the call.
  • The cached release path writes through its supplied address; a null address is not a portable no-op.

fastReallocate

(newSize oldSize ptr -- newPtr) Allocates a new block, copies the shared prefix, and deallocates the old block.
  • Both sizes must be nonzero. Checked violations report Invalid allocation size.
  • The old pointer is invalid after a successful call; the returned mutable pointer remains valid until the next release or resize.
  • The allocate/copy/release path does not check allocation failure before copying. See mplRealloc's allocation-failure warning; do not rely on a safe null result or preservation of the old block on exhaustion.

getHeapUsedSize

(object -- size) Returns heap usage attributable to object as Natx.
  • The default result is 0nx. For a Struct object, non-Ref-like fields are visited recursively; Ref-like fields are not followed.

Example

"control" use
"memory"  use

{} () {} [
  {a: 1i32; b: 2i32;} getHeapUsedSize printStack _:;
] "main" exportFunction

Expected Output During Compilation

0nx

Debug allocation metrics

memoryMetrics

(-- metrics) Returns an immutable view of the debug allocation counters. Available only when debugMemory is TRUE.

getMemoryMetrics

(-- metrics) Returns an immutable view of the current global counters, not a snapshot. Use new to capture a copy. Only the debug public wrappers update these counters; raw allocation calls, direct fast-helper calls, and cache-head storage are not tracked.

Fields

  • Available only when debugMemory is TRUE.
  • memoryCurrentAllocationCount: Nat64 outstanding wrapper-allocation count.
  • memoryTotalAllocationCount: Nat64 cumulative wrapper allocation events, including moved reallocations.
  • memoryCurrentAllocationSize: Nat64 outstanding requested bytes, not rounded cache capacity.
  • memoryTotalAllocationSize: Nat64 cumulative requested bytes for allocation events.
  • memoryMaxAllocationSize: Nat64 peak requested bytes, including the temporary old/new overlap when reallocating to a different address.
  • memoryChecksum: Natx XOR of the tracked allocation addresses.
  • Known issue: allocation failure is not excluded from accounting; a null result can still increment counters. The counters are not an authoritative process-heap or physical-memory measurement.

See also