Store xio_ifp in sv_u in the SV head, reducing XPVIO by 1 pointer.
authorNicholas Clark <nick@ccl4.org>
Wed, 30 Jun 2010 09:46:09 +0000 (10:46 +0100)
committerNicholas Clark <nick@ccl4.org>
Wed, 30 Jun 2010 09:46:09 +0000 (10:46 +0100)
When accessing a file handle for reading, this reduces pointer dereferences by
1, which will reduce CPU cache pressure.

As SVt_PVIO is also the default type provided to source filters, the code needs
to allow them to continue to use the sv_u for SvPVX(). Re-use the existing
IOf_FAKE_DIRP to signal this, as it's only set when a source filter is added.

sv.c
sv.h

diff --git a/sv.c b/sv.c
index 3111c75..b06c14a 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -5757,7 +5757,8 @@ Perl_sv_clear(pTHX_ register SV *const sv)
        if (IoIFP(sv) &&
            IoIFP(sv) != PerlIO_stdin() &&
            IoIFP(sv) != PerlIO_stdout() &&
-           IoIFP(sv) != PerlIO_stderr())
+           IoIFP(sv) != PerlIO_stderr() &&
+           !(IoFLAGS(sv) & IOf_FAKE_DIRP))
        {
            io_close(MUTABLE_IO(sv), FALSE);
        }
@@ -5839,7 +5840,8 @@ Perl_sv_clear(pTHX_ register SV *const sv)
            }
        }
 #ifdef PERL_OLD_COPY_ON_WRITE
-       else if (SvPVX_const(sv)) {
+       else if (SvPVX_const(sv)
+                && !(SvTYPE(sv) == SVt_PVIO && !(IoFLAGS(sv) & IOf_FAKE_DIRP))) {
             if (SvIsCOW(sv)) {
                 if (DEBUG_C_TEST) {
                     PerlIO_printf(Perl_debug_log, "Copy on write: clear\n");
@@ -5857,7 +5859,8 @@ Perl_sv_clear(pTHX_ register SV *const sv)
             }
        }
 #else
-       else if (SvPVX_const(sv) && SvLEN(sv))
+       else if (SvPVX_const(sv) && SvLEN(sv)
+                && !(SvTYPE(sv) == SVt_PVIO && !(IoFLAGS(sv) & IOf_FAKE_DIRP)))
            Safefree(SvPVX_mutable(sv));
        else if (SvPVX_const(sv) && SvREADONLY(sv) && SvFAKE(sv)) {
            unshare_hek(SvSHARED_HEK_FROM_PV(SvPVX_const(sv)));
@@ -11200,11 +11203,6 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
                    Perl_rvpv_dup(aTHX_ dstr, sstr, param);
                break;
            case SVt_PVIO:
-               IoIFP(dstr)     = fp_dup(IoIFP(dstr), IoTYPE(dstr), param);
-               if (IoOFP(dstr) == IoIFP(sstr))
-                   IoOFP(dstr) = IoIFP(dstr);
-               else
-                   IoOFP(dstr) = fp_dup(IoOFP(dstr), IoTYPE(dstr), param);
                /* PL_parser->rsfp_filters entries have fake IoDIRP() */
                if(IoFLAGS(dstr) & IOf_FAKE_DIRP) {
                    /* I have no idea why fake dirp (rsfps)
@@ -11223,7 +11221,12 @@ S_sv_dup_common(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
                        NOOP;
                        /* IoDIRP(dstr) is already a copy of IoDIRP(sstr)  */
                    }
+                   IoIFP(dstr) = fp_dup(IoIFP(sstr), IoTYPE(dstr), param);
                }
+               if (IoOFP(dstr) == IoIFP(sstr))
+                   IoOFP(dstr) = IoIFP(dstr);
+               else
+                   IoOFP(dstr) = fp_dup(IoOFP(dstr), IoTYPE(dstr), param);
                IoTOP_NAME(dstr)        = SAVEPV(IoTOP_NAME(dstr));
                IoFMT_NAME(dstr)        = SAVEPV(IoFMT_NAME(dstr));
                IoBOTTOM_NAME(dstr)     = SAVEPV(IoBOTTOM_NAME(dstr));
diff --git a/sv.h b/sv.h
index adadab3..bc75d1e 100644 (file)
--- a/sv.h
+++ b/sv.h
@@ -106,6 +106,7 @@ typedef struct hek HEK;
        SV**    svu_array;              \
        HE**    svu_hash;               \
        GP*     svu_gp;                 \
+       PerlIO *svu_fp;                 \
     }  sv_u
 
 
@@ -509,8 +510,8 @@ struct xpvfm {
 struct xpvio {
     _XPV_HEAD;
     union _xivu xiv_u;
-    PerlIO *   xio_ifp;        /* ifp and ofp are normally the same */
-    PerlIO *   xio_ofp;        /* but sockets need separate streams */
+    /* ifp and ofp are normally the same, but sockets need separate streams */
+    PerlIO *   xio_ofp;
     /* Cray addresses everything by word boundaries (64 bits) and
      * code and data pointers cannot be mixed (which is exactly what
      * Perl_filter_add() tries to do with the dirp), hence the
@@ -1054,6 +1055,8 @@ the scalar's value cannot change unless written to.
            assert(SvTYPE(_svcur) != SVt_PVAV);                         \
            assert(SvTYPE(_svcur) != SVt_PVHV);                         \
            assert(!isGV_with_GP(_svcur));                              \
+           assert(!(SvTYPE(_svcur) == SVt_PVIO                         \
+                    && !(IoFLAGS(_svcur) & IOf_FAKE_DIRP)));           \
            &(((XPV*) MUTABLE_PTR(SvANY(_svcur)))->xpv_cur);            \
         }))
 #    define SvIVX(sv)                                                  \
@@ -1100,6 +1103,8 @@ the scalar's value cannot change unless written to.
            assert(SvTYPE(_svrv) != SVt_PVCV);                          \
            assert(SvTYPE(_svrv) != SVt_PVFM);                          \
            assert(!isGV_with_GP(_svrv));                               \
+           assert(!(SvTYPE(_svrv) == SVt_PVIO                          \
+                    && !(IoFLAGS(_svrv) & IOf_FAKE_DIRP)));            \
            &((_svrv)->sv_u.svu_rv);                                    \
         }))
 #    define SvRV_const(sv)                                             \
@@ -1110,6 +1115,8 @@ the scalar's value cannot change unless written to.
            assert(SvTYPE(_svrv) != SVt_PVCV);                          \
            assert(SvTYPE(_svrv) != SVt_PVFM);                          \
            assert(!isGV_with_GP(_svrv));                               \
+           assert(!(SvTYPE(_svrv) == SVt_PVIO                          \
+                    && !(IoFLAGS(_svrv) & IOf_FAKE_DIRP)));            \
            (_svrv)->sv_u.svu_rv;                                       \
         })
 #    define SvMAGIC(sv)                                                        \
@@ -1185,6 +1192,8 @@ the scalar's value cannot change unless written to.
                assert(SvTYPE(sv) != SVt_PVAV);         \
                assert(SvTYPE(sv) != SVt_PVHV);         \
                assert(!isGV_with_GP(sv));              \
+               assert(!(SvTYPE(sv) == SVt_PVIO         \
+                    && !(IoFLAGS(sv) & IOf_FAKE_DIRP))); \
                ((sv)->sv_u.svu_pv = (val)); } STMT_END
 #define SvUV_set(sv, val) \
        STMT_START { assert(SvTYPE(sv) == SVt_IV || SvTYPE(sv) >= SVt_PVIV); \
@@ -1200,6 +1209,8 @@ the scalar's value cannot change unless written to.
                assert(SvTYPE(sv) != SVt_PVCV);         \
                assert(SvTYPE(sv) != SVt_PVFM);         \
                assert(!isGV_with_GP(sv));              \
+               assert(!(SvTYPE(sv) == SVt_PVIO         \
+                    && !(IoFLAGS(sv) & IOf_FAKE_DIRP))); \
                 ((sv)->sv_u.svu_rv = (val)); } STMT_END
 #define SvMAGIC_set(sv, val) \
         STMT_START { assert(SvTYPE(sv) >= SVt_PVMG); \
@@ -1212,12 +1223,16 @@ the scalar's value cannot change unless written to.
                assert(SvTYPE(sv) != SVt_PVAV);         \
                assert(SvTYPE(sv) != SVt_PVHV);         \
                assert(!isGV_with_GP(sv));              \
+               assert(!(SvTYPE(sv) == SVt_PVIO         \
+                    && !(IoFLAGS(sv) & IOf_FAKE_DIRP))); \
                (((XPV*)  SvANY(sv))->xpv_cur = (val)); } STMT_END
 #define SvLEN_set(sv, val) \
        STMT_START { assert(SvTYPE(sv) >= SVt_PV); \
                assert(SvTYPE(sv) != SVt_PVAV); \
                assert(SvTYPE(sv) != SVt_PVHV); \
                assert(!isGV_with_GP(sv));      \
+               assert(!(SvTYPE(sv) == SVt_PVIO         \
+                    && !(IoFLAGS(sv) & IOf_FAKE_DIRP))); \
                (((XPV*)  SvANY(sv))->xpv_len = (val)); } STMT_END
 #define SvEND_set(sv, val) \
        STMT_START { assert(SvTYPE(sv) >= SVt_PV); \
@@ -1311,7 +1326,7 @@ the scalar's value cannot change unless written to.
 #define LvTARGOFF(sv)  ((XPVLV*)  SvANY(sv))->xlv_targoff
 #define LvTARGLEN(sv)  ((XPVLV*)  SvANY(sv))->xlv_targlen
 
-#define IoIFP(sv)      ((XPVIO*)  SvANY(sv))->xio_ifp
+#define IoIFP(sv)      (sv)->sv_u.svu_fp
 #define IoOFP(sv)      ((XPVIO*)  SvANY(sv))->xio_ofp
 #define IoDIRP(sv)     ((XPVIO*)  SvANY(sv))->xio_dirp
 #define IoANY(sv)      ((XPVIO*)  SvANY(sv))->xio_any