I have a rather technical explanation I’ve written before, but that’s probably more detail than is needed here! Unfortunately, the three heaps are not documented anywhere official, so it just comes down to who’s worked with the compiler enough to understand the internals. Which is basically…me.
But the short version is:
- The main heap (actually a stack) is where variables, lists (LISP-style cons cells), and unrecognized dictionary words live. There’s no garbage collection or anything; instead, when a query is finished (basically a function call returning), the stack pointer is yanked back to where it was at the start of that query. This means everything on the stack above it is lost to the aether and will be overwritten by new variables and so on.
- The auxiliary heap (also actually a stack) is where choice points and call frames live. It works like the call stack in a language like C or C++: it enables recursion, by giving each function call (instead of each function) a record of its own. The compiler also stashes things here from time to time when it needs them. You know how I just said the stack pointer is reset after every function call? This is where the old value of the stack pointer is stored to make that work.
- The long-term heap (actually a heap this time!) is where global variables and object variables live. Anything stored in a global or object variable is transferred to this heap so that it can survive the end of its query. Every time a long-term variable is reassigned, its old block of memory is freed, and a new block of memory is allocated for its new value.