Ken Fox <[EMAIL PROTECTED]> writes:
>I'd like to see *minimal* overhead for simple scalars -- if we
>could cram immediates (like small integers and booleans) directly
>into the "SV *" that seems like a big win.

Agreed.

>
>For foreign objects, I'm not sure why you're forcing a two level
>dispatch. Why not let the foreign code register dispatches directly
>in the scalar's vtbl? If we did it that way, a foreign object
>is just:
>
>[SV *] --> [type_code, flags, pointer]
>
>The type_code defines the vtbl to use when calling an op on
>the object. Calling an op is just calling vtbl[type_code].the_op(SV *).

I am tempted to turn that round - have the vtable pointer in the SV *,
and the type code (if we need it) in the vtable - that saves a deref on 
dispatch - where we need speed - and still allows type code access for 
meta ops.

typedef struct p6vtable {
  unsigned tFlags : 28;    // flags for "class" 
  unsigned type   : 4;     // "type code" 
  int (*init)(SV *);       // constructor
  int (*cleanup)(SV *);    // destructor 
  IV  (*SvIV)(SV *); 
  NV  (*SvNV)(SV *); 
  ...
} p6vtable;

I think we could allow slot for double in the base class, which 
on many platforms would allow an IV and a void * as well.

typedef struct p6SVBASE
{
 p6vtable *vtable;
 u32 iFlags; 
 union {
  struct {
   void *ptr;
   IV   iv;
  } words;
  NV   nv; 
 } data;
} p6SVBASE;

One can imagine a "small PV" which splits sv->data.words.iv into two shorts
for SvCUR and offset. (SvLEN can off course live at the other end of ptr - 
after all if we re-malloc we need to go mess there anyway.)
I think perl5 may have squeezed the base class a little too small.

So accessors become things like (inline just to avoid #define for now) :

inline IV
SvIV(SV *sv)
{
 return (*sv->vtable.SvIV)(sv);
}

With the simplest case being

IV 
nativeIV(SV *sv)
{
 return sv->data.words.iv;
}

-- 
Nick Ing-Simmons

Reply via email to