Heap
Heap exposes three static helpers for inspecting the allocator’s state at runtime — total free bytes, the size of the biggest single free extent, and the compile-time heap capacity. All methods are static.
#import <Heap.xt>Heap is meaningful only on heap-allocator targets — currently xl-shadow, xe-nobank, xt, xe-heap, and the multi-bank rambo* / compy* variants. On bump-allocator targets the allocator keeps no free-list metadata, so size() and largest() would return misleading values.
Methods
Section titled “Methods”static u32 size(void); // current free bytes (across every reserved bank)static u16 largest(void); // biggest single contiguous free extentstatic u32 totalSize(void); // compile-time heap capacity (constant)u32 free = Heap.size();u16 max = Heap.largest();u32 total = Heap.totalSize();
Stdio.printf("heap: %lu free of %lu (largest extent: %u)\n", free, total, max);Why the types differ
Section titled “Why the types differ”size()andtotalSize()areu32because a multi-bank heap can easily exceed 64 KB. For example,xe-heapreserves 6 banks × 16 KB = 96 KB;rambo576goes higher.largest()isu16because a single free extent cannot span a bank boundary — it’s bounded by the flat region size or one 16 KB bank, both of which fit in 16 bits.
What “free” means
Section titled “What “free” means”All three counts are in bytes and include the 4-byte per-block header (2-byte size + 2-byte retain count) that the allocator stores in front of every allocation. A new u8[100] therefore consumes 104 bytes from the size() total, not 100.
Use it for “will my allocation fit?”
Section titled “Use it for “will my allocation fit?””size() reports total free bytes summed across every free extent. First-fit allocation can’t satisfy a request larger than the largest single extent, even if size() is much bigger — fragmentation can leave you with plenty of total free and nothing usefully large.
if (Heap.largest() < (u16)needed + 4) { Stdio.print("not enough contiguous heap; bailing\n"); return;}u8@ buf = new u8[needed];The +4 accounts for the per-block header overhead; if you forget it the allocator will refuse the request even though largest() says yes.
Performance
Section titled “Performance”size()walks the free list in every reserved bank — O(free-block count). Safe to call often, but not free.largest()walks the same lists with a running max — same cost class assize().totalSize()is a linker-resolved constant (heap_total_bytes) emitted at build time. Free at runtime.