compiler awareness week
[p5sagit/p5-mst-13.2.git] / sv.c
diff --git a/sv.c b/sv.c
index a2c4835..e8c47f5 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -1173,19 +1173,19 @@ S_more_xpv(pTHX)
 STATIC void
 S_more_xpviv(pTHX)
 {
-    XPVIV* xpviv;
-    XPVIV* xpvivend;
-    New(714, xpviv, PERL_ARENA_SIZE/sizeof(XPVIV), XPVIV);
-    *((XPVIV**)xpviv) = PL_xpviv_arenaroot;
+    xpviv_allocated* xpviv;
+    xpviv_allocated* xpvivend;
+    New(713, xpviv, PERL_ARENA_SIZE/sizeof(xpviv_allocated), xpviv_allocated);
+    *((xpviv_allocated**)xpviv) = PL_xpviv_arenaroot;
     PL_xpviv_arenaroot = xpviv;
 
-    xpvivend = &xpviv[PERL_ARENA_SIZE / sizeof(XPVIV) - 1];
+    xpvivend = &xpviv[PERL_ARENA_SIZE / sizeof(xpviv_allocated) - 1];
     PL_xpviv_root = ++xpviv;
     while (xpviv < xpvivend) {
-       *((XPVIV**)xpviv) = xpviv + 1;
+       *((xpviv_allocated**)xpviv) = xpviv + 1;
        xpviv++;
     }
-    *((XPVIV**)xpviv) = 0;
+    *((xpviv_allocated**)xpviv) = 0;
 }
 
 /* allocate another arena's worth of struct xpvnv */
@@ -1417,14 +1417,20 @@ S_del_xpv(pTHX_ XPV *p)
 STATIC XPVIV*
 S_new_xpviv(pTHX)
 {
-    XPVIV* xpviv;
+    xpviv_allocated* xpviv;
     LOCK_SV_MUTEX;
     if (!PL_xpviv_root)
        S_more_xpviv(aTHX);
     xpviv = PL_xpviv_root;
-    PL_xpviv_root = *(XPVIV**)xpviv;
+    PL_xpviv_root = *(xpviv_allocated**)xpviv;
     UNLOCK_SV_MUTEX;
-    return xpviv;
+    /* If xpviv_allocated is the same structure as XPVIV then the two OFFSETs
+       sum to zero, and the pointer is unchanged. If the allocated structure
+       is smaller (no initial IV actually allocated) then the net effect is
+       to subtract the size of the IV from the pointer, to return a new pointer
+       as if an initial IV were actually allocated.  */
+    return (XPVIV*)((char*)xpviv - STRUCT_OFFSET(XPVIV, xpv_cur)
+                 + STRUCT_OFFSET(xpviv_allocated, xpv_cur));
 }
 
 /* return a struct xpviv to the free list */
@@ -1432,9 +1438,12 @@ S_new_xpviv(pTHX)
 STATIC void
 S_del_xpviv(pTHX_ XPVIV *p)
 {
+    xpviv_allocated* xpviv
+       = (xpviv_allocated*)((char*)(p) + STRUCT_OFFSET(XPVIV, xpv_cur)
+                          - STRUCT_OFFSET(xpviv_allocated, xpv_cur));
     LOCK_SV_MUTEX;
-    *(XPVIV**)p = PL_xpviv_root;
-    PL_xpviv_root = p;
+    *(xpviv_allocated**)xpviv = PL_xpviv_root;
+    PL_xpviv_root = xpviv;
     UNLOCK_SV_MUTEX;
 }
 
@@ -1845,7 +1854,7 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
     case SVt_NULL:
        Perl_croak(aTHX_ "Can't upgrade to undef");
     case SVt_IV:
-       SvANY(sv) = (XPVIV*)((char*)&(sv->sv_u.sv_iv) - STRUCT_OFFSET(XPVIV, xiv_iv));
+       SvANY(sv) = (XPVIV*)((char*)&(sv->sv_u.svu_iv) - STRUCT_OFFSET(XPVIV, xiv_iv));
        SvIV_set(sv, iv);
        break;
     case SVt_NV:
@@ -1853,7 +1862,7 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
        SvNV_set(sv, nv);
        break;
     case SVt_RV:
-       SvANY(sv) = &sv->sv_u.sv_rv;
+       SvANY(sv) = &sv->sv_u.svu_rv;
        SvRV_set(sv, (SV*)pv);
        break;
     case SVt_PVHV:
@@ -1872,8 +1881,6 @@ Perl_sv_upgrade(pTHX_ register SV *sv, U32 mt)
            AvALLOC(sv) = 0;
            AvARYLEN(sv)= 0;
            AvREAL_only(sv);
-           SvIV_set(sv, 0);
-           SvNV_set(sv, 0.0);
        }
        /* to here.  */
        /* XXX? Only SVt_NULL is ever upgraded to AV or HV?  */
@@ -2594,7 +2601,7 @@ Perl_sv_2iv_flags(pTHX_ register SV *sv, I32 flags)
     }
     else if (SvPOKp(sv) && SvLEN(sv)) {
        UV value;
-       const int numtype = grok_number(SvPVX(sv), SvCUR(sv), &value);
+       const int numtype = grok_number(SvPVX_const(sv), SvCUR(sv), &value);
        /* We want to avoid a possible problem when we cache an IV which
           may be later translated to an NV, and the resulting NV is not
           the same as the direct translation of the initial string
@@ -2897,7 +2904,7 @@ Perl_sv_2uv_flags(pTHX_ register SV *sv, I32 flags)
     }
     else if (SvPOKp(sv) && SvLEN(sv)) {
        UV value;
-       const int numtype = grok_number(SvPVX(sv), SvCUR(sv), &value);
+       const int numtype = grok_number(SvPVX_const(sv), SvCUR(sv), &value);
 
        /* We want to avoid a possible problem when we cache a UV which
           may be later translated to an NV, and the resulting NV is not
@@ -3069,7 +3076,7 @@ Perl_sv_2nv(pTHX_ register SV *sv)
            return SvNVX(sv);
        if (SvPOKp(sv) && SvLEN(sv)) {
            if (ckWARN(WARN_NUMERIC) && !SvIOKp(sv) &&
-               !grok_number(SvPVX(sv), SvCUR(sv), NULL))
+               !grok_number(SvPVX_const(sv), SvCUR(sv), NULL))
                not_a_number(sv);
            return Atof(SvPVX(sv));
        }
@@ -3291,7 +3298,7 @@ STATIC UV
 S_asUV(pTHX_ SV *sv)
 {
     UV value;
-    int numtype = grok_number(SvPVX(sv), SvCUR(sv), &value);
+    const int numtype = grok_number(SvPVX_const(sv), SvCUR(sv), &value);
 
     if ((numtype & (IS_NUMBER_IN_UV | IS_NUMBER_NOT_INT))
        == IS_NUMBER_IN_UV) {
@@ -3799,9 +3806,9 @@ Perl_sv_2bool(pTHX_ register SV *sv)
     if (SvPOKp(sv)) {
        register XPV* Xpvtmp;
        if ((Xpvtmp = (XPV*)SvANY(sv)) &&
-               (*sv->sv_u.sv_pv > '0' ||
+               (*sv->sv_u.svu_pv > '0' ||
                Xpvtmp->xpv_cur > 1 ||
-               (Xpvtmp->xpv_cur && *sv->sv_u.sv_pv != '0')))
+               (Xpvtmp->xpv_cur && *sv->sv_u.svu_pv != '0')))
            return 1;
        else
            return 0;
@@ -5762,9 +5769,9 @@ Perl_sv_replace(pTHX_ register SV *sv, register SV *nsv)
        it would be unclear.  */
     if(SvTYPE(sv) == SVt_IV)
        SvANY(sv)
-           = (XPVIV*)((char*)&(sv->sv_u.sv_iv) - STRUCT_OFFSET(XPVIV, xiv_iv));
+           = (XPVIV*)((char*)&(sv->sv_u.svu_iv) - STRUCT_OFFSET(XPVIV, xiv_iv));
     else if (SvTYPE(sv) == SVt_RV) {
-       SvANY(sv) = &sv->sv_u.sv_rv;
+       SvANY(sv) = &sv->sv_u.svu_rv;
     }
        
 
@@ -7287,7 +7294,7 @@ Perl_sv_inc(pTHX_ register SV *sv)
        /* Got to punt this as an integer if needs be, but we don't issue
           warnings. Probably ought to make the sv_iv_please() that does
           the conversion if possible, and silently.  */
-       int numtype = grok_number(SvPVX(sv), SvCUR(sv), NULL);
+       const int numtype = grok_number(SvPVX_const(sv), SvCUR(sv), NULL);
        if (numtype && !(numtype & IS_NUMBER_INFINITY)) {
            /* Need to try really hard to see if it's an integer.
               9.22337203685478e+18 is an integer.
@@ -7435,7 +7442,7 @@ Perl_sv_dec(pTHX_ register SV *sv)
     }
 #ifdef PERL_PRESERVE_IVUV
     {
-       int numtype = grok_number(SvPVX(sv), SvCUR(sv), NULL);
+       const int numtype = grok_number(SvPVX_const(sv), SvCUR(sv), NULL);
        if (numtype && !(numtype & IS_NUMBER_INFINITY)) {
            /* Need to try really hard to see if it's an integer.
               9.22337203685478e+18 is an integer.
@@ -8041,7 +8048,7 @@ Perl_sv_true(pTHX_ register SV *sv)
        const register XPV* tXpv;
        if ((tXpv = (XPV*)SvANY(sv)) &&
                (tXpv->xpv_cur > 1 ||
-               (tXpv->xpv_cur && *sv->sv_u.sv_pv != '0')))
+               (tXpv->xpv_cur && *sv->sv_u.svu_pv != '0')))
            return 1;
        else
            return 0;
@@ -10728,7 +10735,7 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
        SvANY(dstr)     = NULL;
        break;
     case SVt_IV:
-       SvANY(dstr)     = (XPVIV*)((char*)&(dstr->sv_u.sv_iv) - STRUCT_OFFSET(XPVIV, xiv_iv));
+       SvANY(dstr)     = (XPVIV*)((char*)&(dstr->sv_u.svu_iv) - STRUCT_OFFSET(XPVIV, xiv_iv));
        SvIV_set(dstr, SvIVX(sstr));
        break;
     case SVt_NV:
@@ -10736,7 +10743,7 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
        SvNV_set(dstr, SvNVX(sstr));
        break;
     case SVt_RV:
-       SvANY(dstr)     = &(dstr->sv_u.sv_rv);
+       SvANY(dstr)     = &(dstr->sv_u.svu_rv);
        Perl_rvpv_dup(aTHX_ dstr, sstr, param);
        break;
     case SVt_PV:
@@ -10877,8 +10884,6 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
        SvANY(dstr)     = new_XPVAV();
        SvCUR_set(dstr, SvCUR(sstr));
        SvLEN_set(dstr, SvLEN(sstr));
-       SvIV_set(dstr, SvIVX(sstr));
-       SvNV_set(dstr, SvNVX(sstr));
        SvMAGIC_set(dstr, mg_dup(SvMAGIC(sstr), param));
        SvSTASH_set(dstr, hv_dup_inc(SvSTASH(sstr), param));
        AvARYLEN((AV*)dstr) = sv_dup_inc(AvARYLEN((AV*)sstr), param);
@@ -10913,22 +10918,32 @@ Perl_sv_dup(pTHX_ SV *sstr, CLONE_PARAMS* param)
        SvANY(dstr)     = new_XPVHV();
        SvCUR_set(dstr, SvCUR(sstr));
        SvLEN_set(dstr, SvLEN(sstr));
-       SvIV_set(dstr, SvIVX(sstr));
-       SvNV_set(dstr, SvNVX(sstr));
+       HvTOTALKEYS(dstr) = HvTOTALKEYS(sstr);
        SvMAGIC_set(dstr, mg_dup(SvMAGIC(sstr), param));
        SvSTASH_set(dstr, hv_dup_inc(SvSTASH(sstr), param));
        {
-           const char *hvname = HvNAME_get((HV*)sstr);
            struct xpvhv_aux *aux = ((XPVHV *)SvANY(sstr))->xhv_aux;
+           HEK *hvname = 0;
 
            if (aux) {
-               New(0, ((XPVHV *)SvANY(dstr))->xhv_aux, 1, struct xpvhv_aux);
-               HvRITER_set((HV*)dstr, HvRITER_get((HV*)sstr));
-               /* FIXME strlen HvNAME  */
-               Perl_hv_name_set(aTHX_ (HV*) dstr, hvname,
-                                hvname ? strlen(hvname) : 0,
-                                0);
-           } else {
+               I32 riter = aux->xhv_riter;
+
+               hvname = aux->xhv_name;
+               if (hvname || riter != -1) {
+                   struct xpvhv_aux *d_aux;
+
+                   New(0, d_aux, 1, struct xpvhv_aux);
+
+                   d_aux->xhv_riter = riter;
+                   d_aux->xhv_eiter = 0;
+                   d_aux->xhv_name = hvname ? hek_dup(hvname, param) : hvname;
+
+                   ((XPVHV *)SvANY(dstr))->xhv_aux = d_aux;
+               } else {
+                   ((XPVHV *)SvANY(dstr))->xhv_aux = 0;
+               }
+           }
+           else {
                ((XPVHV *)SvANY(dstr))->xhv_aux = 0;
            }
            if (HvARRAY((HV*)sstr)) {
@@ -11463,6 +11478,7 @@ do_mark_cloneable_stash(pTHX_ SV *sv)
     const char *hvname = HvNAME_get((HV*)sv);
     if (hvname) {
        GV* cloner = gv_fetchmethod_autoload((HV*)sv, "CLONE_SKIP", 0);
+       STRLEN len = HvNAMELEN_get((HV*)sv);
        SvFLAGS(sv) |= SVphv_CLONEABLE; /* clone objects by default */
        if (cloner && GvCV(cloner)) {
            dSP;
@@ -11471,7 +11487,7 @@ do_mark_cloneable_stash(pTHX_ SV *sv)
            ENTER;
            SAVETMPS;
            PUSHMARK(SP);
-           XPUSHs(sv_2mortal(newSVpv(hvname, 0)));
+           XPUSHs(sv_2mortal(newSVpvn(hvname, len)));
            PUTBACK;
            call_sv((SV*)GvCV(cloner), G_SCALAR);
            SPAGAIN;
@@ -11663,6 +11679,9 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     PL_debug           = proto_perl->Idebug;
 
+    PL_hash_seed       = proto_perl->Ihash_seed;
+    PL_rehash_seed     = proto_perl->Irehash_seed;
+
 #ifdef USE_REENTRANT_API
     /* XXX: things like -Dm will segfault here in perlio, but doing
      *  PERL_SET_CONTEXT(proto_perl);
@@ -11673,6 +11692,8 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     /* create SV map for pointer relocation */
     PL_ptr_table = ptr_table_new();
+    /* and one for finding shared hash keys quickly */
+    PL_shared_hek_table = ptr_table_new();
 
     /* initialize these special pointers as early as possible */
     SvANY(&PL_sv_undef)                = NULL;
@@ -11705,7 +11726,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     /* create (a non-shared!) shared string table */
     PL_strtab          = newHV();
     HvSHAREKEYS_off(PL_strtab);
-    hv_ksplit(PL_strtab, 512);
+    hv_ksplit(PL_strtab, HvTOTALKEYS(proto_perl->Istrtab));
     ptr_table_store(PL_ptr_table, proto_perl->Istrtab, PL_strtab);
 
     PL_compiling = proto_perl->Icompiling;
@@ -12103,8 +12124,6 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
 
     PL_glob_index      = proto_perl->Iglob_index;
     PL_srand_called    = proto_perl->Isrand_called;
-    PL_hash_seed       = proto_perl->Ihash_seed;
-    PL_rehash_seed     = proto_perl->Irehash_seed;
     PL_uudmap['M']     = 0;            /* reinits on demand */
     PL_bitcount                = Nullch;       /* reinits on demand */
 
@@ -12303,6 +12322,8 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
     if (!(flags & CLONEf_KEEP_PTR_TABLE)) {
         ptr_table_free(PL_ptr_table);
         PL_ptr_table = NULL;
+        ptr_table_free(PL_shared_hek_table);
+        PL_shared_hek_table = NULL;
     }
 
     /* Call the ->CLONE method, if it exists, for each of the stashes
@@ -12316,7 +12337,7 @@ perl_clone_using(PerlInterpreter *proto_perl, UV flags,
            ENTER;
            SAVETMPS;
            PUSHMARK(SP);
-           XPUSHs(sv_2mortal(newSVpv(HvNAME_get(stash), 0)));
+           XPUSHs(sv_2mortal(newSVpvn(HvNAME_get(stash), HvNAMELEN_get(stash))));
            PUTBACK;
            call_sv((SV*)GvCV(cloner), G_DISCARD);
            FREETMPS;