diff options
author | Gurusamy Sarathy <gsar@cpan.org> | 2000-07-15 09:05:09 -0700 |
---|---|---|
committer | Jarkko Hietaniemi <jhi@iki.fi> | 2000-07-24 02:58:52 +0000 |
commit | 544f31531e7cbe3b4e7571d94c56f36d53f647fa (patch) | |
tree | 4d466bf2d469fbf2933216cd4017063f3627c4e5 /pp_ctl.c | |
parent | 66417f8481fa145150d67cc9c9373be6a91826a9 (diff) | |
download | perl-544f31531e7cbe3b4e7571d94c56f36d53f647fa.tar.gz |
Documentation to explain the behaviour of map().
Subject: Re: Map is still slow
Message-Id: <200007152305.QAA26887@molotok.activestate.com>
p4raw-id: //depot/perl@6428
Diffstat (limited to 'pp_ctl.c')
-rw-r--r-- | pp_ctl.c | 34 |
1 files changed, 24 insertions, 10 deletions
@@ -725,36 +725,49 @@ PP(pp_mapstart) PP(pp_mapwhile) { djSP; - I32 diff = (SP - PL_stack_base) - *PL_markstack_ptr; + I32 items = (SP - PL_stack_base) - *PL_markstack_ptr; /* how many new items */ I32 count; I32 shift; SV** src; SV** dst; + /* first, move source pointer to the next item in the source list */ ++PL_markstack_ptr[-1]; - if (diff) { - if (diff > PL_markstack_ptr[-1] - PL_markstack_ptr[-2]) { - shift = diff - (PL_markstack_ptr[-1] - PL_markstack_ptr[-2]); - count = (SP - PL_stack_base) - PL_markstack_ptr[-1] + 2; + + /* if there are new items, push them into the destination list */ + if (items) { + /* might need to make room back there first */ + if (items > PL_markstack_ptr[-1] - PL_markstack_ptr[-2]) { + /* XXX this implementation is very pessimal because the stack + * is repeatedly extended for every set of items. Is possible + * to do this without any stack extension or copying at all + * by maintaining a separate list over which the map iterates + * (like foreach does). */ + + /* everything in the stack after the destination list moves + * towards the end the stack by the amount of room needed */ + shift = items - (PL_markstack_ptr[-1] - PL_markstack_ptr[-2]); + + /* items to shift up (accounting for the moved source pointer) */ + count = (SP - PL_stack_base) - (PL_markstack_ptr[-1] - 1); EXTEND(SP,shift); src = SP; dst = (SP += shift); PL_markstack_ptr[-1] += shift; *PL_markstack_ptr += shift; - while (--count) + while (count--) *dst-- = *src--; } - dst = PL_stack_base + (PL_markstack_ptr[-2] += diff) - 1; - ++diff; - while (--diff) + /* copy the new items down to the destination list */ + dst = PL_stack_base + (PL_markstack_ptr[-2] += items) - 1; + while (items--) *dst-- = SvTEMP(TOPs) ? POPs : sv_mortalcopy(POPs); } LEAVE; /* exit inner scope */ /* All done yet? */ if (PL_markstack_ptr[-1] > *PL_markstack_ptr) { - I32 items; I32 gimme = GIMME_V; (void)POPMARK; /* pop top */ @@ -777,6 +790,7 @@ PP(pp_mapwhile) ENTER; /* enter inner scope */ SAVEVPTR(PL_curpm); + /* set $_ to the new source item */ src = PL_stack_base[PL_markstack_ptr[-1]]; SvTEMP_off(src); DEFSV = src; |