Hi,

for a pairwise-map, thusly:

    my @c = pairwise { $a + $b } @a, @b;

I have written an XSUB that I think is doing dangerous stuff with the
Perl stack. Here's the gist of it:
    
PROTOTYPE: &[EMAIL PROTECTED]@

    SV *code;       /* codeblock argument */
    AV *avs[2];     /* holds the two arrays passed by reference */
    SV **oldsp;
    
    ...
    EXTEND(SP, maxitems);
    oldsp = PL_stack_base;
    ENTER;
    for (i = 0; i < maxitems; i++) {
        SV **svp = av_fetch(avs[0], i, FALSE);
        GvSV(PL_firstgv) = svp ? *svp : &PL_sv_undef;
        svp = av_fetch(avs[1], i, FALSE);
        GvSV(PL_secondgv) = svp ? *svp : &PL_sv_undef;
        PUSHMARK(SP);
        PUTBACK;
        call_sv(code, G_EVAL|G_SCALAR);
        SPAGAIN;
        SvREFCNT_inc(*PL_stack_sp++);
    }
    PL_stack_base = oldsp;
    LEAVE;
    XSRETURN(maxitems);

My goal was to avoid the safe but stupid way of allocating an array of
'maxitems' SVs in which I temporarily store the return value of the
codeblock and later copy that down to SP.

Instead I came up with the above after many unsuccesful attempts of
avoiding copying any SVs. I store PL_stack_base's address in a safe
place. In the for-loop I advance PL_stack_sp to the position where the
return value of 'code' shall appear in the return list. That way, 'code'
will directly put its return value into this position and afterwards I
just have to increment its refcount (that's the reason why I don't use
the customary SAVETMPS/FREETMPS couple here). Finally I restore the old
PL_stack_base pointer.

How robust is this approach? Empirical tests say it's ok but then, I
don't really understand the perl stack stuff very well. I tried to mimic
what perl's map does, but I don't understand at all what pp_mapwhile is
doing.

Cheers,
Tassilo
-- 
$_=q#",}])!JAPH!qq(tsuJ[{@"tnirp}3..0}_$;//::niam/s~=)]3[))_$-3(rellac(=_$({
pam{rekcahbus})(rekcah{lrePbus})(lreP{rehtonabus})!JAPH!qq(rehtona{tsuJbus#;
$_=reverse,s+(?<=sub).+q#q!'"qq.\t$&."'!#+sexisexiixesixeseg;y~\n~~dddd;eval

Reply via email to