John Tobey <[EMAIL PROTECTED]> writes:
>Nick Ing-Simmons <[EMAIL PROTECTED]> wrote:
>> John Tobey <[EMAIL PROTECTED]> writes:
>> >Dan Sugalski <[EMAIL PROTECTED]> wrote:
>> >> Yup, and I realized one of my big problems to GCs that move memory 
>> >> (references that are pointers and such) really isn't, if we keep the 
>> >> two-level variable structure that we have now. The 'main' SV structure 
>> >> won't move, while the guts that the equivalent of sv_any points to can 
>> >> without a problem.
>> >
>> >I certainly hope this data layout factoid is still subject to change.
>> 
>> Having an SV have a fixed address is handy for C extensions.
>> The 'entity' has got to have some 'handle' to defines its existance.
>> If not the SV* data structure then what is it that defines the thing?
>
>Just like in Perl, if you want a reference to it, put it somewhere and
>use a pointer.  Otherwise, use it by value.  (three words, or two if
>flags are dropped, or four if vptr is added, or one if everything is
>crammed into a pointer with low bits commandeered).

So what exactly is your point here ?
We currently (perl5) have the "token" being:

struct sv {
    void*       sv_any;         /* pointer to something */
    U32         sv_refcnt;      /* how many references to us */
    U32         sv_flags;       /* what we are */
};

3 words (which is a "funny" number in a binary world.

(With the type hiding in flags as a small int.)

Current perl6 "token" proposed by RFC 35 is:

    struct {
      IV GC_data;                 // REFCNT
      void *variable_data;        // sv_any, possibly used for IV, RV 
      IV flags;                   // sv_flags  
      vtable_t *vtable;           // _new_ - explcit type 
      void *sync_data;            // _new_ - for threads etc.
    }

5 words (which is if anything a slighty worse number...)

I think I would make it 4 or 8 words:

    struct {
      vtable_t *vtable;           // _new_ - explcit type 
      IV flags_and_GC;            // sv_flags 
      void *sync_data;            // _new_ - for threads etc.
      void *variable_data;        // sv_any, possibly used for IV, RV 
    }

That squeezes flags and GC into a word - no big deal for 'mark' bit
but if we have a REFCNT it had better be 8 or 16 bits or update will 
be too many cycles.

So my own favourite right now allows a little more - to keep data and token
together for cache, and to avoid extra malloc() in simple cases.
Some variant like:

    struct {
      vtable_t *vtable;           // _new_ - explcit type 
      IV flags;                   // sv_flags  
      void *sync_data;            // _new_ - for threads etc.
      IV GC_data;                 // REFCNT
      void *ptr;                  // SvPV, SvRV
      IV   iv;                    // SvIV, SvCUR/SvOFF
      NV   nv;                    // SvNV
    }

The other extreme might be just a pointer with LS 3 bits snaffled for 
"mark" and two "vital" flags - but that just means above lives via the 
pointer and everything is one more de-ref away _AND_ needs masking 
except for "all flags zero" case (which had better be the common one).

As I recall my LISP it has two pointers + flags

-- 
Nick Ing-Simmons

Reply via email to