Nicholas Clark wrote:

On Sat, Jun 18, 2005 at 12:15:39PM -0600, Jim Cromie wrote:
we now have

struct STRUCT_SV {              /* struct sv { */
    void*       sv_any;         /* pointer to something */
    U32         sv_refcnt;      /* how many references to us */
    U32         sv_flags;       /* what we are */
    union {
        IV      svu_iv;
        UV      svu_uv;
        SV*     svu_rv;         /* pointer to another SV */
        char*   svu_pv;         /* pointer to malloced string */
        SV**    svu_array;
    }           sv_u;
}


wherein the 2 'data' fields are separated by the 'management' fields.

It seems potentially useful to juggle them so that the 2 data are
contiguous, then we could (after a bit more tweaking)
store doubles, complex numbers, and other nasties.

IOW:

struct gv {
   SV_DATA(XPVCV*);
   SV_MGMT;
};



The problem with doing this is that all the access macros assume that the
thing they are accessing are at some offset in the structure that sv_any
points to. Hence the offset games for IVs, so that svu_iv still is at the
offset the compiler would expect to find it in

struct xpviv {
   NV           xnv_nv;         /* numeric value, if any */
   STRLEN       xpv_cur;        /* length of svu_pv as a C string */
   STRLEN       xpv_len;        /* allocated size */
   union {
        IV      xivu_iv;        /* integer value or pv offset */
        UV      xivu_uv;
        void *  xivu_p1;
   }            xiv_u;
};


So it's not going to be possible to store an NV in the head, if SvNVX() still
looks like this:

#  define SvNVX(sv) ((XPVNV*) SvANY(sv))->xnv_nv


Yes, thats what I meant when I said (ie handwaved) 'after a bit more tweaking'
I probably understated too much ;-)

What the patch proved was that all the access macros, like SvNVX,
are defined robustly enough to not explode when a few fields are moved around.

I probly should have switched SV_DATA & SV_MGMT too, just to
give SvANY and dependents a slap-test. And putting the potentially more variant part of the record in back is probably wize. (I didnt cuz of the likely slowdown the
+2 word offset would do to pointer-chain following though).

I just did this, it also passes most tests (all but lib/Archive/Tar/t/02_methods)
real    6m3.619s
user    3m15.881s
sys     0m16.128s

vs bleadperl
real    6m5.137s
user    3m17.356s
sys     0m18.251s

so theres no glaring slowdown.

wrt bringing NVs into head also, I'll concede that it looks messy/smelly ATM, since NVs are 2x the size of others (correct, on most platforms ?). This blows the 16 byte cache-friendly target size unless rather rude
multi-layer struct-union-struct are devised.

so, lets give that a sniff test:

struct STRUCT_SV {              /* struct sv { */
     U32         sv_refcnt;      /* how many references to us */
     U32         sv_flags;       /* what we are */

   union {
        struct {
                void*       sv_any;         /* pointer to something */
                union {
                  IV      svu_iv;
                  UV      svu_uv;
                  SV*     svu_rv;         /* pointer to another SV */
                  char*   svu_pv;         /* pointer to malloced string */
                  SV**    svu_array;
              }           sv_u;
        NV      svu_nv;
    } un;
}

This trashes the SvANY pointer with 1/2 of an NV (again assuming Ive got 2x 
right),
but we dont really need it for this variant of an SV do we ?
(again, assuming that macros are adjusted).

Id almost talked myself into trying this, but then went grepping for svu_iv and friends.
I didnt see enough of them to convince me that I understood.  Call me lazy.


I'm not sure how much slowdown there would be from implementing a conditional
in that based on some other flag.

speaking of flags, I note that weve got 15 svtypes defined.
Its hard to imagine getting to 31 or 63, so there are arguably 2 bits available.
Not that any new ones are needed for the above.

Nicholas Clark


Reply via email to