UPDATE
As per my revelations in sort this data, here is a bit of
an adjusted report on the av.c source.
Here's the relevant portion from
av.c in the 5.6
source:
/* this is Perl_av_unshift()
it unshifts 'num' undef values to an array */
/* determine how much non-used spaced is left
that's been allocated for this array */
i = AvARRAY(av) - AvALLOC(av);
/* if there's room left... */
if (i) {
/* if there's more room than we need, just use 'num' */
if (i > num) i = num;
/* this will set 'num' to 0 if we had enough room */
/* 'num' is now how many new undef values we need added */
num -= i;
AvMAX(av) += i; /* set the highest subscript??? */
AvFILLp(av) += i; /* add to highest subscript */
SvPVX(av) = (char*)(AvARRAY(av) - i); /* where Perl's array starts
+*/
}
/* if there wasn't enough room already... */
if (num) {
i = AvFILLp(av); /* highest subscript */
av_extend(av, i + num); /* extend array to i+num elements */
AvFILLp(av) += num; /* add to highest subscript */
ary = AvARRAY(av); /* get at the array */
Move(ary, ary + num, i + 1, SV*); /* slide elements up */
do {
ary[--num] = &PL_sv_undef; /* set new elements to undef */
} while (num);
}
Ok, so
unshift() has to do a lot of sliding the
elements up if there's not already some free space generated
by a call to
shift().
What
shift() does is simply slide the pointer up
one notch, which is very fast (which provides free space for
unshift() later). It stores the value in
*AvARRAY(av) into
retval, and then sets
*AvARRAY(av) to the C equivalent of Perl's
undef value. Then it moves the pointer that marks
the beginning of the array to
AvARRAY(av) + 1. It
also subtracts one from the max subscript and the length of
the array. Then it returns
retval.
<revelation>I'm beginning to grok the source
code! Look out!
</revelation>.
japhy --
Perl and Regex Hacker