[Ada] Spurious secondary stack depletion
This patch reimplements the secondary stack allocation logic to eliminate an
issue which causes the memory index to overflow while the stack itself uses
very little memory, thus causing a spurious Storage_Error.
The issue in details:
The total amount of memory that the secondary stack can accomodate is dictated
by System.Parameters.Size_Type which is really an Integer, giving roughly 2 GB
of storage.
The secondary stack is comprised of multiple frames which logically form a
contiguous array of memory. Each frame maintans a range over which it operates,
where
Low bound = Previous frame's high bound + 1
High bound = Previous frame's high bound + Frame size
The allocation logic starts by first checking whether the current top frame
(which may not be the "last" frame in the secondary stack) has enough memory to
fit an object. If it does, then that frame is used. If it does not, the logic
then examines the subsequent frames, while carrying out the following actions:
* If the frame is too small to fit the object, it is deleted
* If the frame is big enough to fit the object, it is used
If all the frames were too small (and thus deleted), a new frame is added which
is big enough to fit the object.
Due to an issue with the deletion logic, the last frame would never be deleted.
Since any new frame's range is based on the previous frame's range, the new
range would keep growing, even though the secondary stack may have very few
frames in use. Eventually this growth overflows the memory index type.
The overflow of the memory index type happens only when the secondary stack
is full, and thus signals a Storage_Error. Due to the spurious growth of the
ranges, the overflow happens much faster and results in a bogus stack depleton.
The issue manifests only when each new memory request to the secondary stack is
slightly bigger than the previous memory request, thus prompring the secondary
stack to delete all its frames, and create a new one.
2018-05-25 Hristian Kirtchev <kirtchev@adacore.com>
gcc/ada/
* libgnat/s-secsta.adb (SS_Allocate): Reimplemented.
(SS_Allocate_Dynamic): New routine. The allocation logic is now split
into three distring cases rather than in one loop which attempts to
handle all three cases. This rewrite eliminates an issue where the last
frame of the stack cannot be freed, thus causing the memory range of a
new frame to approach the overflow point of the memory index type.
Since the overflow is logically treated as a
too-much-memory-on-the-stack scenario, it causes a bogus Storage_Error.
(SS_Allocate_Static): New routine. The routine factorizes the static
secondary stack-related code from the former SS_Allocate.
gcc/testsuite/
* gnat.dg/sec_stack2.adb: New testcase.
From-SVN: r260736