Revert change #27295, which I thought fixed builds on Win32.
[p5sagit/p5-mst-13.2.git] / sv.c
diff --git a/sv.c b/sv.c
index f4e661c..1dc7283 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -642,8 +642,9 @@ Perl_sv_free_arenas(pTHX)
 #else
     S_free_arena(aTHX_ (void**) PL_body_arenas);
 #endif
+    PL_body_arenas = 0;
 
-    for (i=0; i<SVt_LAST; i++)
+    for (i=0; i<PERL_ARENA_ROOTS_SIZE; i++)
        PL_body_roots[i] = 0;
 
     Safefree(PL_nice_chunk);
@@ -841,13 +842,14 @@ has no consequence at this time.
 */
 
 struct body_details {
-    size_t body_size;  /* Size to allocate  */
-    size_t copy;       /* Size of structure to copy (may be shorter)  */
-    size_t offset;
-    bool cant_upgrade; /* Cannot upgrade this type */
-    bool zero_nv;      /* zero the NV when upgrading from this */
-    bool arena;                /* Allocated from an arena */
-    size_t arena_size; /* Size of arena to allocate */
+    U8 body_size;      /* Size to allocate  */
+    U8 copy;           /* Size of structure to copy (may be shorter)  */
+    U8 offset;
+    unsigned int type : 4;         /* We have space for a sanity check.  */
+    unsigned int cant_upgrade : 1;  /* Cannot upgrade this type */
+    unsigned int zero_nv : 1;      /* zero the NV when upgrading from this */
+    unsigned int arena : 1;        /* Allocated from an arena */
+    size_t arena_size;             /* Size of arena to allocate */
 };
 
 #define HADNV FALSE
@@ -904,85 +906,83 @@ struct xpv {
        + sizeof (((type*)SvANY((SV*)0))->last_member)
 
 static const struct body_details bodies_by_type[] = {
-    { sizeof(HE), 0, 0, FALSE, NONV, NOARENA, FIT_ARENA(0, sizeof(HE)) },
+    { sizeof(HE), 0, 0, SVt_NULL,
+      FALSE, NONV, NOARENA, FIT_ARENA(0, sizeof(HE)) },
 
     /* IVs are in the head, so the allocation size is 0.
        However, the slot is overloaded for PTEs.  */
     { sizeof(struct ptr_tbl_ent), /* This is used for PTEs.  */
       sizeof(IV), /* This is used to copy out the IV body.  */
-      STRUCT_OFFSET(XPVIV, xiv_iv), FALSE, NONV,
+      STRUCT_OFFSET(XPVIV, xiv_iv), SVt_IV, FALSE, NONV,
       NOARENA /* IVS don't need an arena  */,
       /* But PTEs need to know the size of their arena  */
       FIT_ARENA(0, sizeof(struct ptr_tbl_ent))
     },
 
     /* 8 bytes on most ILP32 with IEEE doubles */
-    { sizeof(NV), sizeof(NV), 0, FALSE, HADNV, HASARENA,
+    { sizeof(NV), sizeof(NV), 0, SVt_NV, FALSE, HADNV, HASARENA,
       FIT_ARENA(0, sizeof(NV)) },
 
     /* RVs are in the head now.  */
-    { 0, 0, 0, FALSE, NONV, NOARENA, 0 },
+    { 0, 0, 0, SVt_RV, FALSE, NONV, NOARENA, 0 },
 
     /* 8 bytes on most ILP32 with IEEE doubles */
     { sizeof(xpv_allocated),
       copy_length(XPV, xpv_len)
       - relative_STRUCT_OFFSET(xpv_allocated, XPV, xpv_cur),
       + relative_STRUCT_OFFSET(xpv_allocated, XPV, xpv_cur),
-      FALSE, NONV, HASARENA, FIT_ARENA(0, sizeof(xpv_allocated)) },
+      SVt_PV, FALSE, NONV, HASARENA, FIT_ARENA(0, sizeof(xpv_allocated)) },
 
     /* 12 */
     { sizeof(xpviv_allocated),
       copy_length(XPVIV, xiv_u)
       - relative_STRUCT_OFFSET(xpviv_allocated, XPVIV, xpv_cur),
       + relative_STRUCT_OFFSET(xpviv_allocated, XPVIV, xpv_cur),
-      FALSE, NONV, HASARENA, FIT_ARENA(0, sizeof(xpviv_allocated)) },
+      SVt_PVIV, FALSE, NONV, HASARENA, FIT_ARENA(0, sizeof(xpviv_allocated)) },
 
     /* 20 */
-    { sizeof(XPVNV), copy_length(XPVNV, xiv_u), 0, FALSE, HADNV,
+    { sizeof(XPVNV), copy_length(XPVNV, xiv_u), 0, SVt_PVNV, FALSE, HADNV,
       HASARENA, FIT_ARENA(0, sizeof(XPVNV)) },
 
     /* 28 */
-    { sizeof(XPVMG), copy_length(XPVMG, xmg_stash), 0, FALSE, HADNV,
+    { sizeof(XPVMG), copy_length(XPVMG, xmg_stash), 0, SVt_PVMG, FALSE, HADNV,
       HASARENA, FIT_ARENA(0, sizeof(XPVMG)) },
     
     /* 36 */
-    { sizeof(XPVBM), sizeof(XPVBM), 0, TRUE, HADNV,
+    { sizeof(XPVBM), sizeof(XPVBM), 0, SVt_PVBM, TRUE, HADNV,
       HASARENA, FIT_ARENA(0, sizeof(XPVBM)) },
 
     /* 48 */
-    { sizeof(XPVGV), sizeof(XPVGV), 0, TRUE, HADNV,
+    { sizeof(XPVGV), sizeof(XPVGV), 0, SVt_PVGV, TRUE, HADNV,
       HASARENA, FIT_ARENA(0, sizeof(XPVGV)) },
     
     /* 64 */
-    { sizeof(XPVLV), sizeof(XPVLV), 0, TRUE, HADNV,
+    { sizeof(XPVLV), sizeof(XPVLV), 0, SVt_PVLV, TRUE, HADNV,
       HASARENA, FIT_ARENA(0, sizeof(XPVLV)) },
 
     { sizeof(xpvav_allocated),
       copy_length(XPVAV, xmg_stash)
       - relative_STRUCT_OFFSET(xpvav_allocated, XPVAV, xav_fill),
       + relative_STRUCT_OFFSET(xpvav_allocated, XPVAV, xav_fill),
-      TRUE, HADNV, HASARENA, FIT_ARENA(0, sizeof(xpvav_allocated)) },
+      SVt_PVAV, TRUE, HADNV, HASARENA, FIT_ARENA(0, sizeof(xpvav_allocated)) },
 
     { sizeof(xpvhv_allocated),
       copy_length(XPVHV, xmg_stash)
       - relative_STRUCT_OFFSET(xpvhv_allocated, XPVHV, xhv_fill),
       + relative_STRUCT_OFFSET(xpvhv_allocated, XPVHV, xhv_fill),
-      TRUE, HADNV, HASARENA, FIT_ARENA(0, sizeof(xpvhv_allocated)) },
+      SVt_PVHV, TRUE, HADNV, HASARENA, FIT_ARENA(0, sizeof(xpvhv_allocated)) },
 
     /* 56 */
-    { sizeof(xpvcv_allocated), sizeof(XPVCV)
-      - relative_STRUCT_OFFSET(xpvcv_allocated, XPVCV, xpv_cur),
+    { sizeof(xpvcv_allocated), sizeof(xpvcv_allocated),
       + relative_STRUCT_OFFSET(xpvcv_allocated, XPVCV, xpv_cur),
-      TRUE, NONV, HASARENA, FIT_ARENA(0, sizeof(xpvcv_allocated)) },
+      SVt_PVCV, TRUE, NONV, HASARENA, FIT_ARENA(0, sizeof(xpvcv_allocated)) },
 
-    { sizeof(xpvfm_allocated),
-      sizeof(XPVFM)
-      - relative_STRUCT_OFFSET(xpvfm_allocated, XPVFM, xpv_cur),
+    { sizeof(xpvfm_allocated), sizeof(xpvfm_allocated),
       + relative_STRUCT_OFFSET(xpvfm_allocated, XPVFM, xpv_cur),
-      TRUE, NONV, NOARENA, FIT_ARENA(20, sizeof(xpvfm_allocated)) },
+      SVt_PVFM, TRUE, NONV, NOARENA, FIT_ARENA(20, sizeof(xpvfm_allocated)) },
 
     /* XPVIO is 84 bytes, fits 48x */
-    { sizeof(XPVIO), sizeof(XPVIO), 0, TRUE, HADNV,
+    { sizeof(XPVIO), sizeof(XPVIO), 0, SVt_PVIO, TRUE, HADNV,
       HASARENA, FIT_ARENA(24, sizeof(XPVIO)) },
 };
 
@@ -1054,6 +1054,10 @@ static const struct body_details bodies_by_type[] = {
 #define new_NOARENAZ(details) \
        my_safecalloc((details)->body_size + (details)->offset)
 
+#ifdef DEBUGGING
+static bool done_sanity_check;
+#endif
+
 STATIC void *
 S_more_bodies (pTHX_ svtype sv_type)
 {
@@ -1065,6 +1069,18 @@ S_more_bodies (pTHX_ svtype sv_type)
     const char *end;
 
     assert(bdp->arena_size);
+
+#ifdef DEBUGGING
+    if (!done_sanity_check) {
+       int i = SVt_LAST;
+
+       done_sanity_check = TRUE;
+
+       while (i--)
+           assert (bodies_by_type[i].type == i);
+    }
+#endif
+
     start = (char*) Perl_get_arena(aTHX_ bdp->arena_size);
 
     end = start + bdp->arena_size - body_size;
@@ -1224,7 +1240,7 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 new_type)
        /* This flag bit is used to mean other things in other scalar types.
           Given that it only has meaning inside the pad, it shouldn't be set
           on anything that can get upgraded.  */
-       assert((SvFLAGS(sv) & SVpad_TYPED) == 0);
+       assert(!SvPAD_TYPED(sv));
        break;
     default:
        if (old_type_details->cant_upgrade)
@@ -1713,6 +1729,31 @@ Perl_looks_like_number(pTHX_ SV *sv)
     return grok_number(sbegin, len, NULL);
 }
 
+STATIC char *
+S_glob_2inpuv(pTHX_ GV *gv, STRLEN *len, bool want_number)
+{
+    const U32 wasfake = SvFLAGS(gv) & SVf_FAKE;
+    SV *const buffer = sv_newmortal();
+
+    /* FAKE globs can get coerced, so need to turn this off temporarily if it
+       is on.  */
+    SvFAKE_off(gv);
+    gv_efullname3(buffer, gv, "*");
+    SvFLAGS(gv) |= wasfake;
+
+    if (want_number) {
+       /* We know that all GVs stringify to something that is not-a-number,
+          so no need to test that.  */
+       if (ckWARN(WARN_NUMERIC))
+           not_a_number(buffer);
+       /* We just want something true to return, so that S_sv_2iuv_common
+          can tail call us and return true.  */
+       return (char *) 1;
+    } else {
+       return SvPV(buffer, *len);
+    }
+}
+
 /* Actually, ISO C leaves conversion of UV to IV undefined, but
    until proven guilty, assume that things are not that bad... */
 
@@ -2073,6 +2114,13 @@ S_sv_2iuv_common(pTHX_ SV *sv) {
        }
     }
     else  {
+       if (((SvFLAGS(sv) & (SVp_POK|SVp_SCREAM)) == SVp_SCREAM)
+           && (SvTYPE(sv) == SVt_PVGV || SvTYPE(sv) == SVt_PVLV)) {
+           return PTR2IV(glob_2inpuv((GV *)sv, NULL, TRUE));
+       }
+       if (SvTYPE(sv) == SVt_PVGV)
+           sv_dump(sv);
+
        if (!(SvFLAGS(sv) & SVs_PADTMP)) {
            if (!PL_localizing && ckWARN(WARN_UNINITIALIZED))
                report_uninit(sv);
@@ -2420,6 +2468,12 @@ Perl_sv_2nv(pTHX_ register SV *sv)
 #endif /* NV_PRESERVES_UV */
     }
     else  {
+       if (((SvFLAGS(sv) & (SVp_POK|SVp_SCREAM)) == SVp_SCREAM)
+           && (SvTYPE(sv) == SVt_PVGV || SvTYPE(sv) == SVt_PVLV)) {
+           glob_2inpuv((GV *)sv, NULL, TRUE);
+           return 0.0;
+       }
+
        if (!PL_localizing && !(SvFLAGS(sv) & SVs_PADTMP) && ckWARN(WARN_UNINITIALIZED))
            report_uninit(sv);
        assert (SvTYPE(sv) >= SVt_NV);
@@ -2752,6 +2806,11 @@ Perl_sv_2pv_flags(pTHX_ register SV *sv, STRLEN *lp, I32 flags)
 #endif
     }
     else {
+       if (((SvFLAGS(sv) & (SVp_POK|SVp_SCREAM)) == SVp_SCREAM)
+           && (SvTYPE(sv) == SVt_PVGV || SvTYPE(sv) == SVt_PVLV)) {
+           return glob_2inpuv((GV *)sv, lp, FALSE);
+       }
+
        if (!PL_localizing && !(SvFLAGS(sv) & SVs_PADTMP) && ckWARN(WARN_UNINITIALIZED))
            report_uninit(sv);
        if (lp)
@@ -2882,8 +2941,13 @@ Perl_sv_2bool(pTHX_ register SV *sv)
        else {
            if (SvNOKp(sv))
                return SvNVX(sv) != 0.0;
-           else
-               return FALSE;
+           else {
+               if ((SvFLAGS(sv) & SVp_SCREAM)
+                   && (SvTYPE(sv) == (SVt_PVGV) || SvTYPE(sv) == (SVt_PVLV)))
+                   return TRUE;
+               else
+                   return FALSE;
+           }
        }
     }
 }
@@ -3124,7 +3188,6 @@ S_glob_assign_glob(pTHX_ SV *dstr, SV *sstr, const int dtype)
        /* don't upgrade SVt_PVLV: it can hold a glob */
        if (dtype != SVt_PVLV)
            sv_upgrade(dstr, SVt_PVGV);
-       sv_magic(dstr, dstr, PERL_MAGIC_glob, NULL, 0);
        GvSTASH(dstr) = GvSTASH(sstr);
        if (GvSTASH(dstr))
            Perl_sv_add_backref(aTHX_ (SV*)GvSTASH(dstr), dstr);
@@ -3140,6 +3203,7 @@ S_glob_assign_glob(pTHX_ SV *dstr, SV *sstr, const int dtype)
 #endif
 
     (void)SvOK_off(dstr);
+    SvSCREAM_on(dstr);
     GvINTRO_off(dstr);         /* one-shot flag */
     gp_free((GV*)dstr);
     GvGP(dstr) = gp_ref(GvGP(sstr));
@@ -3305,8 +3369,6 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
                sv_upgrade(dstr, SVt_IV);
                break;
            case SVt_NV:
-               sv_upgrade(dstr, SVt_PVNV);
-               break;
            case SVt_RV:
            case SVt_PV:
                sv_upgrade(dstr, SVt_PVIV);
@@ -3411,6 +3473,8 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
            SvUPGRADE(dstr, (U32)stype);
     }
 
+    /* dstr may have been upgraded.  */
+    dtype = SvTYPE(dstr);
     sflags = SvFLAGS(sstr);
 
     if (sflags & SVf_ROK) {
@@ -3449,6 +3513,21 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
        assert(!(sflags & SVf_NOK));
        assert(!(sflags & SVf_IOK));
     }
+    else if (dtype == SVt_PVGV) {
+       if (!(sflags & SVf_OK)) {
+           if (ckWARN(WARN_MISC))
+               Perl_warner(aTHX_ packWARN(WARN_MISC),
+                           "Undefined value assigned to typeglob");
+       }
+       else {
+           GV *gv = gv_fetchsv(sstr, GV_ADD, SVt_PVGV);
+           if (dstr != (SV*)gv) {
+               if (GvGP(dstr))
+                   gp_free((GV*)dstr);
+               GvGP(dstr) = gp_ref(GvGP(gv));
+           }
+       }
+    }
     else if (sflags & SVp_POK) {
         bool isSwipe = 0;
 
@@ -3603,9 +3682,17 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV *sstr, I32 flags)
        }
     }
     else {
-       if (dtype == SVt_PVGV) {
-           if (ckWARN(WARN_MISC))
-               Perl_warner(aTHX_ packWARN(WARN_MISC), "Undefined value assigned to typeglob");
+       if ((stype == SVt_PVGV || stype == SVt_PVLV)
+                && (sflags & SVp_SCREAM)) {
+           /* This stringification rule for globs is spread in 3 places.
+              This feels bad. FIXME.  */
+           const U32 wasfake = sflags & SVf_FAKE;
+
+           /* FAKE globs can get coerced, so need to turn this off
+              temporarily if it is on.  */
+           SvFAKE_off(sstr);
+           gv_efullname3(dstr, (GV *)sstr, "*");
+           SvFLAGS(sstr) |= wasfake;
        }
        else
            (void)SvOK_off(dstr);
@@ -4434,9 +4521,6 @@ Perl_sv_magic(pTHX_ register SV *sv, SV *obj, int how, const char *name, I32 nam
     case PERL_MAGIC_defelem:
        vtable = &PL_vtbl_defelem;
        break;
-    case PERL_MAGIC_glob:
-       vtable = &PL_vtbl_glob;
-       break;
     case PERL_MAGIC_arylen:
        vtable = &PL_vtbl_arylen;
        break;
@@ -4958,7 +5042,7 @@ Perl_sv_clear(pTHX_ register SV *sv)
     if (type >= SVt_PVMG) {
        if (SvMAGIC(sv))
            mg_free(sv);
-       if (type == SVt_PVMG && SvFLAGS(sv) & SVpad_TYPED)
+       if (type == SVt_PVMG && SvPAD_TYPED(sv))
            SvREFCNT_dec(SvSTASH(sv));
     }
     switch (type) {
@@ -7594,16 +7678,19 @@ S_sv_unglob(pTHX_ SV *sv)
 {
     dVAR;
     void *xpvmg;
+    SV *temp = sv_newmortal();
 
     assert(SvTYPE(sv) == SVt_PVGV);
     SvFAKE_off(sv);
+    gv_efullname3(temp, (GV *) sv, "*");
+
     if (GvGP(sv))
        gp_free((GV*)sv);
     if (GvSTASH(sv)) {
        sv_del_backref((SV*)GvSTASH(sv), sv);
        GvSTASH(sv) = NULL;
     }
-    sv_unmagic(sv, PERL_MAGIC_glob);
+    SvSCREAM_off(sv);
     Safefree(GvNAME(sv));
     GvMULTI_off(sv);
 
@@ -7615,6 +7702,10 @@ S_sv_unglob(pTHX_ SV *sv)
 
     SvFLAGS(sv) &= ~SVTYPEMASK;
     SvFLAGS(sv) |= SVt_PVMG;
+
+    /* Intentionally not calling any local SET magic, as this isn't so much a
+       set operation as merely an internal storage change.  */
+    sv_setsv_flags(sv, temp, 0);
 }
 
 /*
@@ -9832,7 +9923,7 @@ Perl_sv_dup(pTHX_ const SV *sstr, CLONE_PARAMS* param)
                if (!CvISXSUB(dstr))
                    CvROOT(dstr) = OpREFCNT_inc(CvROOT(dstr));
                OP_REFCNT_UNLOCK;
-               if (CvCONST(dstr)) {
+               if (CvCONST(dstr) && CvISXSUB(dstr)) {
                    CvXSUBANY(dstr).any_ptr = GvUNIQUE(CvGV(dstr)) ?
                        SvREFCNT_inc(CvXSUBANY(dstr).any_ptr) :
                        sv_dup_inc((SV *)CvXSUBANY(dstr).any_ptr, param);