- the size of the list is known when you create a stack frame, as in c:
int xs[n] = {0};
- when the list grows, it grows in that subroutine and not some callee, for example using alloca();- the list is built on a stack that isn't the one you have to pop your return address off of; examples include perl's data stack, ada's secondary stack, forth's operand stack, forth's dictionary, or an mlkit region. in these cases you can even return the dynamically built structure to a caller;
- each new callee adds some fixed number of items to a linked list, such as, in c
void with_fill(color *c,
env *e,
void (*cb)(void*, env*),
void *userdata)
{
env ne = {
.prop = PROP_FILL_COLOR,
.val = c,
.parent = e };
cb(userdata, &ne);
}
look ma, no heap"var data: MyObject" is on the stack. "var arr: array[1000, MyObject]" is allocated on the stack sequentially.
Only dynamic seq or ref types use the heap by default.