C++ Logo

std-discussion

Advanced search

Re: Structured dynamic stack allocation

From: Tiago Freire <tmiguelf_at_[hidden]>
Date: Wed, 15 Jan 2025 08:41:27 +0000
> And anyway, what's the point? Shrinkable memory allocations already exist on the heap and freeing/shrinking memory is incredibly fast. Memory allocation on the heap is also very fast, if the allocator is using a per-thread arena like it should. So stack-based allocation should only be used for incredibly simple allocations that can be very fast and are also not very big. Otherwise, just use the heap.

Well yes. It is intended to support lightweight algorithms that benefit from variable memory size but where the memory requirements are statistically small but theoretically could be much larger, and where dipping into the heap (and the trappings associated with it) causes a disproportional amount of burden that could otherwise be avoided.


> > * A facility that tells you how much stack is available and can be
> > used – So that you don’t accidentally blow up the stack, and you can
> > make an informed decision on either or not you want to allocate
> > something on the stack or fallback to using the heap.

> This probably requires an operating system change and probably the cooperation of the low-level C library, for functions like setcontext() and signal handling on the alternate stack. Given that, I suggest you abandon this requirement.

This is a hard requirement. I've always been uncomfortable with the status quo "hey, you have this piece of memory that you must use in order for your application to even function, it's quite limited in size and be very careful not to go over its limit. And by the way, I'm not going to tell you how much that is, and it's really hard to estimate how much you really need, and it is almost impossible to recover if you mess it up, good luck!"
I've realized that it might need some operating system support, if that's the case so be it, let's see how far we can go and how far we can get to it.
"low-level C library" probably not, if it requires expensive system calls to do it, it almost completely defeats the purpose of it, and you might as well just create your own "alternative stack" that you manage yourself.


> > * A facility to resize how much of the stack is reserved – Which would
> > allow you to decrease the amount of memory as well as increase it
> > (right now we can only increase it with alloca).

> That probably won't work or will be implemented as a "no-op". It would be too complex to deal with a fragmented stack for new allocations to be worth it, and you can't shrink the stack usage while it's fragmented.

The solution to that would be to not fragment it.
The idea is that you would have a single "object" (or perhaps better described as a gadget of sorts) that would represent the usable stack at the level of the function.
A compiler could pre-determined based on how much variables are declared and the scope of what functions get called and what gets returned, how much storage would it need to service the "fixed" portion of the functions needs and pre-reserve that and enforce the "variable" portion to then just happen at the end, allowing to freely expand or contract this region without fragmentation.
You may not necessarily want to implement all functions in this way, but you could opt-in if you whished to use this feature.
But that depends on how compilers make functions reserve the stack right now and still are able to make use of "alloca". I don't know, I'm not familiar, hence I would need help on this, but maybe it already works this way and thus the barrier for implementation would be much lower.

> > Some constraints seem obvious, like functions that use dynamic stack cannot be inlined by the compiler otherwise it could be ill formed.
> Why not? They just modify the stack frame of the function they've been inlined into or the compiler restores the stack when the block is done with.

The problem I was thinking is that you can only move the stack back or forwards, or recover a previous state which typically occurs when returning from a function,
And since an inline function could modify the stack pointer but suppress be return (and subsequentially the reset of the pointer) it could mean that "inlining a function" would not reset the conditions of the caller.
But you might be right, you can just modify the inline code generation such that if dynamic stack manipulation is used, one could save the stack pointer and recover it as the function gets expanded in place.


-----Original Message-----
From: Std-Discussion <std-discussion-bounces_at_lists.isocpp.org> On Behalf Of Thiago Macieira via Std-Discussion
Sent: Tuesday, January 14, 2025 11:00 PM
To: std-discussion_at_[hidden]
Cc: Thiago Macieira <thiago_at_macieira.org>
Subject: Re: [std-discussion] Structured dynamic stack allocation

On Tuesday 14 January 2025 13:14:28 Pacific Standard Time Tiago Freire via Std- Discussion wrote:
> * A facility that tells you how much stack is available and can be
> used – So that you don’t accidentally blow up the stack, and you can
> make an informed decision on either or not you want to allocate
> something on the stack or fallback to using the heap.

This probably requires an operating system change and probably the cooperation of the low-level C library, for functions like setcontext() and signal handling on the alternate stack. Given that, I suggest you abandon this requirement.

> * A facility to resize how much of the stack is reserved – Which would
> allow you to decrease the amount of memory as well as increase it
> (right now we can only increase it with alloca).

That probably won't work or will be implemented as a "no-op". It would be too complex to deal with a fragmented stack for new allocations to be worth it, and you can't shrink the stack usage while it's fragmented.

And anyway, what's the point? Shrinkable memory allocations already exist on the heap and freeing/shrinking memory is incredibly fast. Memory allocation on the heap is also very fast, if the allocator is using a per-thread arena like it should. So stack-based allocation should only be used for incredibly simple allocations that can be very fast and are also not very big. Otherwise, just use the heap.

> Some constraints seem obvious, like functions that use dynamic stack
> can not be inlined by the compiler otherwise it could be ill formed.

Why not? They just modify the stack frame of the function they've been inlined into or the compiler restores the stack when the block is done with.



--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
  Principal Engineer - Intel DCAI Platform & System Engineering



--
Std-Discussion mailing list
Std-Discussion_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-discussion

Received on 2025-01-15 08:41:30