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