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