Dan Sugalski wrote: [sniping to reduce verbiage]
The issue is that the PMC's original vtable assumes (and should, IMHO be _able_ to assume) that it has total control over the PMC's data,
Well... I think I'll disagree here. The *class* vtable can assume this. However that doesn't mean that any random vtable function can.
Yes, that's what I meant by the original vtable. :-)
In addition to the thread autolocking front end and debugging front end vtable functions, both of which can be generic, there's the potential for tracing and auditing front end functions, input data massaging wrappers, and all manner of Truly Evil front (and back) end wrappers that don't need to actually access the guts of the PMC, but can instead rely on the other vtable functions to get the information that they need to operate.
Not that this necessarily mandates passing in the vtable pointer to the functions, but the uses aren't exactly marginal.
Going back to the idea of generating these vtables on the fly (and caching them): each instance of a vtable gets a void* closure in the vtable itself,
so at a certain expense in extra vtables, one could hang a structure off
of that that includes a pointer to the original vtable. E.g. (pseudo-code)
if (we don't have a tracing PerlInt in our cache) { TracePerlIntVtable = clone_vtable(interp, TraceVtable); vtable_set_data(interp, TracePerlIntVtable, PerlIntVtable); cache(TracePerlIntVtable); }
TraceVtable::get_number(INTERP, self) { FLOATVAL f; // I don't have the headers in front of me to get the right field names... VTABLE *my_vtbl = self->vtable; VTABLE *old_vtbl = my_vtbl->private;
self->vtable = old_vtbl; f = self->vtable->get_number(interp, self); TRACE("%p->get_number() = %f", self, f); self->vtable = my_vtbl;
return f; }
With slightly more complicated closures, most of the listed uses can use this method. It's memory-heavy, but not too bad if we need a fair number of PMCs of each wrapped type and the cost gets amortized over them. And this does save an argument to every PMC function and just makes the wrapping classes pay. Where it's suboptimal is for classes like autolocking that really want a closure of their own on every PMC. But then again, that would again probably get into issues of data collisions (except for locking, which has its own reserved area).
Just some thoughts.
-- BKS