This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
make SVs_PADTMP and SVs_PADSTALE share a bit
authorDavid Mitchell <davem@iabyn.com>
Fri, 7 Oct 2011 14:38:56 +0000 (15:38 +0100)
committerDavid Mitchell <davem@iabyn.com>
Fri, 7 Oct 2011 19:07:48 +0000 (20:07 +0100)
SVs_PADSTALE is only meaningful with SVs_PADMY, while
SVs_PADTMP is only meaningful with !SVs_PADMY,
so let them share the same flag bit.

Note that this doesn't yet free a bit in SvFLAGS, as the two
bits are also used for SVpad_STATE, SVpad_TYPED.

(This is is follow-on to 62bb6514085e5eddc42b4fdaf3713ccdb7f1da85.)

dump.c
pad.c
pp_ctl.c
scope.c
sv.c
sv.h

diff --git a/dump.c b/dump.c
index 9990c8d..3281031 100644 (file)
--- a/dump.c
+++ b/dump.c
@@ -1527,10 +1527,12 @@ Perl_do_sv_dump(pTHX_ I32 level, PerlIO *file, SV *sv, I32 nest, I32 maxnest, bo
 
     if (!((flags & SVpad_NAME) == SVpad_NAME
          && (type == SVt_PVMG || type == SVt_PVNV))) {
-       if (flags & SVs_PADSTALE)       sv_catpv(d, "PADSTALE,");
+       if ((flags & SVs_PADMY) && (flags & SVs_PADSTALE))
+           sv_catpv(d, "PADSTALE,");
     }
     if (!((flags & SVpad_NAME) == SVpad_NAME && type == SVt_PVMG)) {
-       if (flags & SVs_PADTMP) sv_catpv(d, "PADTMP,");
+       if (!(flags & SVs_PADMY) && (flags & SVs_PADTMP))
+           sv_catpv(d, "PADTMP,");
        if (flags & SVs_PADMY)  sv_catpv(d, "PADMY,");
     }
     append_flags(d, flags, first_sv_flags_names);
diff --git a/pad.c b/pad.c
index 763e01b..c767b55 100644 (file)
--- a/pad.c
+++ b/pad.c
@@ -1720,7 +1720,7 @@ Perl_pad_free(pTHX_ PADOFFSET po)
     );
 
     if (PL_curpad[po] && PL_curpad[po] != &PL_sv_undef) {
-       SvPADTMP_off(PL_curpad[po]);
+       SvFLAGS(PL_curpad[po]) &= ~SVs_PADTMP; /* also clears SVs_PADSTALE */
     }
     if ((I32)po < PL_padix)
        PL_padix = po - 1;
index 692fdeb..2406761 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -2082,11 +2082,17 @@ PP(pp_dbstate)
 STATIC SV **
 S_adjust_stack_on_leave(pTHX_ SV **newsp, SV **sp, SV **mark, I32 gimme, U32 flags)
 {
+    bool padtmp = 0;
     PERL_ARGS_ASSERT_ADJUST_STACK_ON_LEAVE;
 
+    if (flags & SVs_PADTMP) {
+       flags &= ~SVs_PADTMP;
+       padtmp = 1;
+    }
     if (gimme == G_SCALAR) {
        if (MARK < SP)
-           *++newsp = (SvFLAGS(*SP) & flags) ? *SP : sv_mortalcopy(*SP);
+           *++newsp = ((SvFLAGS(*SP) & flags) || (padtmp && SvPADTMP(*SP)))
+                           ? *SP : sv_mortalcopy(*SP);
        else {
            /* MEXTEND() only updates MARK, so reuse it instead of newsp. */
            MARK = newsp;
@@ -2098,7 +2104,7 @@ S_adjust_stack_on_leave(pTHX_ SV **newsp, SV **sp, SV **mark, I32 gimme, U32 fla
     else if (gimme == G_ARRAY) {
        /* in case LEAVE wipes old return values */
        while (++MARK <= SP) {
-           if (SvFLAGS(*MARK) & flags)
+           if ((SvFLAGS(*MARK) & flags) || (padtmp && SvPADTMP(*MARK)))
                *++newsp = *MARK;
            else {
                *++newsp = sv_mortalcopy(*MARK);
diff --git a/scope.c b/scope.c
index 9ed6475..14664a2 100644 (file)
--- a/scope.c
+++ b/scope.c
@@ -922,7 +922,8 @@ Perl_leave_scope(pTHX_ I32 base)
                SvPADSTALE_on(sv); /* mark as no longer live */
            }
            else {      /* Someone has a claim on this, so abandon it. */
-               const U32 padflags = SvFLAGS(sv) & (SVs_PADMY|SVs_PADTMP);
+               assert(  SvFLAGS(sv) & SVs_PADMY);
+               assert(!(SvFLAGS(sv) & SVs_PADTMP));
                switch (SvTYPE(sv)) {   /* Console ourselves with a new value */
                case SVt_PVAV:  *(SV**)ptr = MUTABLE_SV(newAV());       break;
                case SVt_PVHV:  *(SV**)ptr = MUTABLE_SV(newHV());       break;
@@ -931,7 +932,7 @@ Perl_leave_scope(pTHX_ I32 base)
                SvREFCNT_dec(sv);       /* Cast current value to the winds. */
                /* preserve pad nature, but also mark as not live
                 * for any closure capturing */
-               SvFLAGS(*(SV**)ptr) |= padflags | SVs_PADSTALE;
+               SvFLAGS(*(SV**)ptr) |= (SVs_PADMY|SVs_PADSTALE);
            }
            break;
        case SAVEt_DELETE:
diff --git a/sv.c b/sv.c
index 3360bf4..e92ed2b 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -2228,7 +2228,7 @@ S_sv_2iuv_common(pTHX_ SV *const sv)
        if (isGV_with_GP(sv))
            return glob_2number(MUTABLE_GV(sv));
 
-       if (!(SvFLAGS(sv) & SVs_PADTMP)) {
+       if (!SvPADTMP(sv)) {
            if (!PL_localizing && ckWARN(WARN_UNINITIALIZED))
                report_uninit(sv);
        }
@@ -2613,7 +2613,7 @@ Perl_sv_2nv_flags(pTHX_ register SV *const sv, const I32 flags)
            return 0.0;
        }
 
-       if (!PL_localizing && !(SvFLAGS(sv) & SVs_PADTMP) && ckWARN(WARN_UNINITIALIZED))
+       if (!PL_localizing && !SvPADTMP(sv) && ckWARN(WARN_UNINITIALIZED))
            report_uninit(sv);
        assert (SvTYPE(sv) >= SVt_NV);
        /* Typically the caller expects that sv_any is not NULL now.  */
@@ -2975,7 +2975,7 @@ Perl_sv_2pv_flags(pTHX_ register SV *const sv, STRLEN *const lp, const I32 flags
            *lp = 0;
        if (flags & SV_UNDEF_RETURNS_NULL)
            return NULL;
-       if (!PL_localizing && !(SvFLAGS(sv) & SVs_PADTMP) && ckWARN(WARN_UNINITIALIZED))
+       if (!PL_localizing && !SvPADTMP(sv) && ckWARN(WARN_UNINITIALIZED))
            report_uninit(sv);
        if (SvTYPE(sv) < SVt_PV)
            /* Typically the caller expects that sv_any is not NULL now.  */
diff --git a/sv.h b/sv.h
index bbf41c8..5324256 100644 (file)
--- a/sv.h
+++ b/sv.h
@@ -310,9 +310,10 @@ perform the upgrade if necessary.  See C<svtype>.
                                       CvIMPORTED_CV_ON() if it needs to be
                                       expanded to a real GV */
 
-#define SVs_PADSTALE   0x00010000  /* lexical has gone out of scope */
 #define SVpad_STATE    0x00010000  /* pad name is a "state" var */
-#define SVs_PADTMP     0x00020000  /* in use as tmp */
+#define SVs_PADTMP     0x00020000  /* in use as tmp; only if ! SVs_PADMY */
+#define SVs_PADSTALE   0x00020000  /* lexical has gone out of scope;
+                                       only valid for SVs_PADMY */
 #define SVpad_TYPED    0x00020000  /* pad name is a Typed Lexical */
 #define SVs_PADMY      0x00040000  /* in use a "my" variable */
 #define SVpad_OUR      0x00040000  /* pad name is "our" instead of "my" */
@@ -909,34 +910,41 @@ the scalar's value cannot change unless written to.
 
 #define SvTHINKFIRST(sv)       (SvFLAGS(sv) & SVf_THINKFIRST)
 
-#define SvPADSTALE(sv)         (SvFLAGS(sv) & SVs_PADSTALE)
-#define SvPADSTALE_off(sv)     (SvFLAGS(sv) &= ~SVs_PADSTALE)
+#define SvPADMY(sv)            (SvFLAGS(sv) & SVs_PADMY)
+#define SvPADMY_on(sv)         (SvFLAGS(sv) |= SVs_PADMY)
 
-#define SvPADTMP(sv)           (SvFLAGS(sv) & SVs_PADTMP)
-#define SvPADTMP_off(sv)       (SvFLAGS(sv) &= ~SVs_PADTMP)
+/* SVs_PADTMP and SVs_PADSTALE share the same bit, mediated by SVs_PADMY */
 
-#define SvPADMY(sv)            (SvFLAGS(sv) & SVs_PADMY)
+#define SvPADTMP(sv)   ((SvFLAGS(sv) & (SVs_PADMY|SVs_PADTMP)) == SVs_PADTMP)
+#define SvPADSTALE(sv) ((SvFLAGS(sv) & (SVs_PADMY|SVs_PADSTALE)) \
+                                   == (SVs_PADMY|SVs_PADSTALE))
 
 #if defined (DEBUGGING) && defined(__GNUC__) && !defined(PERL_GCC_BRACE_GROUPS_FORBIDDEN)
-#  define SvPADTMP_on(sv)      ({                                      \
-           SV *const _svpad = MUTABLE_SV(sv);                          \
-           assert(!(SvFLAGS(_svpad) & (SVs_PADMY|SVs_PADSTALE)));      \
-           (SvFLAGS(_svpad) |= SVs_PADTMP);            \
+#  define SvPADTMP_on(sv)      ({                      \
+           SV *const _svpad = MUTABLE_SV(sv);          \
+           assert(!(SvFLAGS(_svpad) & SVs_PADMY));     \
+           SvFLAGS(_svpad) |= SVs_PADTMP;              \
        })
-#  define SvPADMY_on(sv)       ({                                      \
-           SV *const _svpad = MUTABLE_SV(sv);                          \
-           assert(!(SvFLAGS(_svpad) & SVs_PADTMP));    \
-           (SvFLAGS(_svpad) |= SVs_PADMY);             \
+#  define SvPADTMP_off(sv)     ({                      \
+           SV *const _svpad = MUTABLE_SV(sv);          \
+           assert(!(SvFLAGS(_svpad) & SVs_PADMY));     \
+           SvFLAGS(_svpad) &= ~SVs_PADTMP;             \
        })
-#  define SvPADSTALE_on(sv)    ({                                      \
-           SV *const _svpad = MUTABLE_SV(sv);                          \
-           assert(!(SvFLAGS(_svpad) & SVs_PADTMP));    \
-           (SvFLAGS(_svpad) |= SVs_PADSTALE);          \
+#  define SvPADSTALE_on(sv)    ({                      \
+           SV *const _svpad = MUTABLE_SV(sv);          \
+           assert(SvFLAGS(_svpad) & SVs_PADMY);        \
+           SvFLAGS(_svpad) |= SVs_PADSTALE;            \
+       })
+#  define SvPADSTALE_off(sv)   ({                      \
+           SV *const _svpad = MUTABLE_SV(sv);          \
+           assert(SvFLAGS(_svpad) & SVs_PADMY);        \
+           SvFLAGS(_svpad) &= ~SVs_PADSTALE;           \
        })
 #else
 #  define SvPADTMP_on(sv)      (SvFLAGS(sv) |= SVs_PADTMP)
-#  define SvPADMY_on(sv)       (SvFLAGS(sv) |= SVs_PADMY)
+#  define SvPADTMP_off(sv)     (SvFLAGS(sv) &= ~SVs_PADTMP)
 #  define SvPADSTALE_on(sv)    (SvFLAGS(sv) |= SVs_PADSTALE)
+#  define SvPADSTALE_off(sv)   (SvFLAGS(sv) &= ~SVs_PADSTALE)
 #endif
 
 #define SvTEMP(sv)             (SvFLAGS(sv) & SVs_TEMP)