On 02/05/2012 03:58, Marvin Humphrey wrote:
Greets,
I've finished a proof-of-concept app which illustrates one approach to
addressing Clownfish's brittle object struct issue.
The files have been committed to a branch and the README explains the issue
and the proposed solution in detail.
https://svn.apache.org/repos/asf/lucy/branches/LUCY-234-struct-ABI/README
Quoting the README:
This proof-of-concept project adapts Clownfish-style OFFSET vars to encode
both the method offset and fixup information. The "pointer fixup" goes in the
upper 32-bits, and the method offset goes in the lower 32 bits.
static inline void
Dog_speak(Dog *self) {
const uint64_t offsets = Dog_speak_OFFSETS;
void *const view = (char*)self + (int32_t)(offsets >> 32);
char *const method_address = *(char**)self + (uint32_t)offsets;
Dog_speak_t method = *((Dog_speak_t*)method_address);
method(view);
}
It's a very nice idea to tie method offsets and fixups together. But
AFAICS this only works when a calling a method that is defined in the
same class or the superclass of an object, not if it's defined in a
subclass.
Here is an example: Dog overrides the Speak method of the Animal class,
so the fixup for this method will be zero. If we invoke Dog_speak on a
Dog object, the method will receive the Dog object directly and
everything is fine.
Now suppose that a Dog object is passed to a function which accepts an
Animal parameter. This means we have to pass dog->superself which is an
Animal struct with a pointer to the Dog MetaClass. The function then
invokes Animal_speak which is overridden by Dog_speak in Dog. This will
use the method pointers, offsets and fixups of the Dog MetaClass. But
using the zero fixup, the Animal object will be passed to Dog_speak
which is wrong. In this case we'd need a negative fixup to "cast" the
Animal object back to a Dog object.
It's possible to define separate fixups for the Animal struct inside the
Dog object, but this would further complicate the MetaClass initialization.
Another thing I'm wondering about is how casting of objects to
superclasses would work with the scheme you proposed. Casting to the
parent class using ->superself is easy. But I think we'll need an
additional mechanism for casts to superclasses further up in the hierarchy.
Nick