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

Reply via email to