Now Malloc searches the free list instead of walking every block. Because freed blocks are pushed at the head, the most recently freed block is found first - so allocation reuses memory in last-in, first-out order.
Make Malloc search the free list head-first, reusing the most recently freed block that fits.
With the free list in place, Malloc no longer walks allocated blocks: it starts
at freeHead and follows next pointers, taking the first free block that
fits. Because Free pushes onto the head, the block found first is the one freed
most recently - so the allocator reuses memory in last-in, first-out order.
That order is observable, and pinning it is today’s point. Free the block at offset 0, then the block at offset 48; the list head is now 48. A request that fits in a 24-byte block takes block 48 (payload offset 56), not block 0 (payload offset 8), even though block 0 sits at a lower address. First-fit over the free list is not the same as first-fit over addresses - the free list’s order decides. (Coalescing, which would merge adjacent frees, is still to come, so both 48 and 72 sit in the list here.)
// walk the free list from freeHead, first block whose Size fits:for off := a.freeHead; off != -1; off = a.next(off) {size, _ := a.blockAt(off)if size >= need {a.unlink(off) // remove from the free list// split or take whole, mark allocated, return off+8}}