X-Git-Url: https://perl5.git.perl.org/perl5.git/blobdiff_plain/626ed49c374dc371a27e6734ce3d3399c07e2bb4..8aef2117c820d82091fcbab49e8ae3bc5312b954:/pp_sort.c?ds=sidebyside diff --git a/pp_sort.c b/pp_sort.c index 3203f4c..bfd7fa2 100644 --- a/pp_sort.c +++ b/pp_sort.c @@ -1432,7 +1432,7 @@ Sort an array. Here is an example: sortsv(AvARRAY(av), av_top_index(av)+1, Perl_sv_cmp_locale); -Currently this always uses mergesort. See sortsv_flags for a more +Currently this always uses mergesort. See C> for a more flexible routine. =cut @@ -1642,8 +1642,8 @@ PP(pp_sort) PERL_CONTEXT *cx; SV** newsp; const bool oldcatch = CATCH_GET; + I32 old_savestack_ix = PL_savestack_ix; - SAVETMPS; SAVEOP(); CATCH_SET(TRUE); @@ -1657,19 +1657,21 @@ PP(pp_sort) PL_secondgv = MUTABLE_GV(SvREFCNT_inc( gv_fetchpvs("b", GV_ADD|GV_NOTQUAL, SVt_PV) )); + /* make sure the GP isn't removed out from under us for + * the SAVESPTR() */ + save_gp(PL_firstgv, 0); + save_gp(PL_secondgv, 0); + /* we don't want modifications localized */ + GvINTRO_off(PL_firstgv); + GvINTRO_off(PL_secondgv); SAVESPTR(GvSV(PL_firstgv)); SAVESPTR(GvSV(PL_secondgv)); } + gimme = G_SCALAR; PUSHBLOCK(cx, CXt_NULL, PL_stack_base); if (!(flags & OPf_SPECIAL)) { cx->cx_type = CXt_SUB; - cx->blk_gimme = G_SCALAR; - /* If our comparison routine is already active (CvDEPTH is - * is not 0), then PUSHSUB does not increase the refcount, - * so we have to do it ourselves, because the LEAVESUB fur- - * ther down lowers it. */ - if (CvDEPTH(cv)) SvREFCNT_inc_simple_void_NN(cv); PUSHSUB(cx); if (!is_xsub) { PADLIST * const padlist = CvPADLIST(cv); @@ -1678,7 +1680,6 @@ PP(pp_sort) PERL_STACK_OVERFLOW_CHECK(); pad_push(padlist, CvDEPTH(cv)); } - SAVECOMPPAD(); PAD_SET_CUR_NOSAVE(padlist, CvDEPTH(cv)); if (hasargs) { @@ -1687,12 +1688,18 @@ PP(pp_sort) cx->blk_sub.savearray = GvAV(PL_defgv); GvAV(PL_defgv) = MUTABLE_AV(SvREFCNT_inc_simple(av)); - CX_CURPAD_SAVE(cx->blk_sub); - cx->blk_sub.argarray = av; } } } + else { + /* mimic PUSHSUB. Note that we're cheating and using a + * CXt_NULL block as a CXt_SUB block */ + cx->cx_u.cx_blk.blku_old_tmpsfloor = PL_tmps_floor; + PL_tmps_floor = PL_tmps_ix; + } + cx->cx_u.cx_blk.blku_old_savestack_ix = old_savestack_ix; + cx->cx_type |= CXp_MULTICALL; start = p1 - max; @@ -1708,6 +1715,10 @@ PP(pp_sort) POPSUB(cx, sv); LEAVESUB(sv); } + else + /* mimic POPSUB */ + PL_tmps_floor = cx->cx_u.cx_blk.blku_old_tmpsfloor; + POPBLOCK(cx,PL_curpm); PL_stack_sp = newsp; POPSTACK; @@ -1782,12 +1793,10 @@ S_sortcv(pTHX_ SV *const a, SV *const b) PL_op = PL_sortcop; CALLRUNOPS(aTHX); PL_curcop = cop; - if (PL_stack_sp != PL_stack_base + 1) { - assert(PL_stack_sp == PL_stack_base); - result = SvIV(&PL_sv_undef); - } - else - result = SvIV(*PL_stack_sp); + /* entry zero of a stack is always PL_sv_undef, which + * simplifies converting a '()' return into undef in scalar context */ + assert(PL_stack_sp > PL_stack_base || *PL_stack_base == &PL_sv_undef); + result = SvIV(*PL_stack_sp); while (PL_scopestack_ix > oldscopeix) { LEAVE; @@ -1835,12 +1844,10 @@ S_sortcv_stacked(pTHX_ SV *const a, SV *const b) PL_op = PL_sortcop; CALLRUNOPS(aTHX); PL_curcop = cop; - if (PL_stack_sp != PL_stack_base + 1) { - assert(PL_stack_sp == PL_stack_base); - result = SvIV(&PL_sv_undef); - } - else - result = SvIV(*PL_stack_sp); + /* entry zero of a stack is always PL_sv_undef, which + * simplifies converting a '()' return into undef in scalar context */ + assert(PL_stack_sp > PL_stack_base || *PL_stack_base == &PL_sv_undef); + result = SvIV(*PL_stack_sp); while (PL_scopestack_ix > oldscopeix) { LEAVE; @@ -1869,9 +1876,11 @@ S_sortcv_xsub(pTHX_ SV *const a, SV *const b) *++SP = b; PUTBACK; (void)(*CvXSUB(cv))(aTHX_ cv); - if (PL_stack_sp != PL_stack_base + 1) - Perl_croak(aTHX_ "Sort subroutine didn't return single value"); + /* entry zero of a stack is always PL_sv_undef, which + * simplifies converting a '()' return into undef in scalar context */ + assert(PL_stack_sp > PL_stack_base || *PL_stack_base == &PL_sv_undef); result = SvIV(*PL_stack_sp); + while (PL_scopestack_ix > oldscopeix) { LEAVE; }