It is expected that there is exactly one block on initialization. This is the remaining space (< 64K) within the last page after static data.
It is expected that if two adjacent blocks of size K are freed, the merged block doesn't go into the first level list for K*2 because its size is actually larger than that (K + OVERHEAD + K).
It is expected that if memory grows beyond 1GB, that even if all blocks are free'd there are at least two (or even three if the largest block is in the middle) remaining blocks, because a single block must not be larger than 1GB.
It is expected that after other operations have already been performed, being able to allocate 1GB can't be guaranteed anymore, even if there should be enough space left in absolute terms, if prior subdivision prevents it.
It is expected that the second level 0 in first level 0 isn't ever used due to alignment guarantees. Smallest block is 32 bytes (16 bytes overhead + 16 bytes payload if used, respectively linking information if free) in this implementation.
Implementation constants:? bits alignment, ? bits first level, ? bits second level, ? B overhead
First level bitmap
The first level map is a bitmap determining whether free blocks exist in at least one of its respective second levels. In this implementation, the first bit indicates whether a small block (< 256B) exists. Each bit doubles the size.
Second level maps
Second level maps subdivide each first level into multiple lists of subsizes. Each one works similar to the first level bitmap.
Heads
The heads of the actual free lists, one per second level per first level. Values here are pointers into memory. Last item is the address of the special zero-size "used" tail block, which is usually the end of WASM memory minus block overhead.
Allocator
Chose a size to allocate. Annotated list indexes depend on implementation constants but match those of this implementation.
Small blocks:
...
(δ ≙ block overhead)
Common blocks:
(e.g. allocate 3, free middle, check second level)
Large blocks:
Segments
Allocations performed above are tracked here so you can free them again. Note that TLSF alone does not keep track of used blocks (unless free'd and put in a free list again). It is expected that adjacent free blocks become merged automatically.