This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
pp_leavewhen(): skip POPWHEN()
[perl5.git] / pp_sort.c
index 64a67d8..bfd7fa2 100644 (file)
--- a/pp_sort.c
+++ b/pp_sort.c
@@ -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,6 +1657,13 @@ 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));
            }
@@ -1665,11 +1672,6 @@ PP(pp_sort)
            PUSHBLOCK(cx, CXt_NULL, PL_stack_base);
            if (!(flags & OPf_SPECIAL)) {
                cx->cx_type = CXt_SUB;
-               /* 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;