P:\test>p1
# 2368k
@r = 1 .. 1000000;
# 62804k
@r = reverse @r;
# 62812k
@r = reverse 1, @r;
# 71020k
I work that out at around 8MB, or 8 bytes per element. Just enough to build a single linked list of references to the scalars that constitute the elements of the array.
The above (in pp_reverse) is only executed after the array has been moved onto the stack, and in your pseudo-code, @array represents the stack, not the array being reversed.
Agreed. But the reversal, is done by reversing the order ot the linked list of pointers to the scalars. So, if the input argument is a single array, rather than copying the array's linked list onto the stack and set @_ to point to the copy.
I speculate that the SP is pointed at the end of the linked-list that is the array argument, and the linked list is reversed in place. When the sub exits, and the SP is reset to its previous position, the array has been reversed in-situ with no copying to/from the stack required.
That doesn't work when the extra element is passed to reverse, so it has to copy the new element + linked list from the array, to a new lump of memory before calling PP_reverse to re-order the new list. Afterwards, the stash entry for the array is pointed at the new list which was reversed in-situ, and the old list becomes available for garbage collection.
The scalars that form the elements of the array never move at all.
|