Hi, Nick, Kudos for thinking outside the box!
On Sun, Sep 16, 2012 at 7:45 AM, Nick Wellnhofer <[email protected]> wrote: > This leaves the problem of converting the members struct pointers from a > source class to a target class for every method call. The obvious approach > is to somehow work back to the start of the memory region of the object, and > then apply an offset appropriate for the target class. Finding the the start > of the object could be done by adding a field to every members struct. This > would mean two additional fields if you want to keep direct vtable access > (e.g. for method calls) from member structs. All of that looks rather > expensive to me. In addition to being expensive, it seems to me that it would also be complex and error prone. The proposal I made back in May, inspired by C++, was also pretty labyrinthine, but if it had worked the way I'd hoped, the complexity would have been hidden within the method dispatch apparatus -- from the standpoint of the programmer, `self` would have always Just Worked. I'm concerned about making programmers think about any invocant more complicated than `self` on its own. Getting at the `members` struct is also kind of a pain, but at least it's an easily-understood, logical step and hard to mess up. > So in terms of what arguments a method could receive for the 'self' object, > I can see the following solutions (in my order of preference): > > 1. Foo_set_num(Foo *self, int num) > > Cons: > * One additional line of code per method for members lookup > * One additional global variable access per method call for > members lookup I concur with you that this is our best option. I think it's the most sound and straightforward construct/algorithm available to us. It's frustrating that we have those global variable accesses for e.g. `Foo_IVARS_OFFSET`, but at least it's possible to set that variable at VTable-init time and forget about it. What really sticks in my craw is that it's the _ELF_ rules which force it to be looked up every last access, but it's entirely possible that the lookup won't matter in practice. We can benchmark the result of setting all the IVARS_OFFSET variables to compile-time constants if we want to find out how much we're paying. For the record, I thought a little harder today about aliasing and concluded that there's no way to turn off -fno-strict-aliasing even if `self` is allowed to point at different places within an object. Even if `A` does not point at the exact same address as `B`, what matters is that it can still be alias for _the same object_ -- so you have to be pessimistic about caching field values in registers unless your compiler can do serious aliasing analysis and suss out which variables can alias and which can't. Another note: making the transition to members structs will be straightforward, if a little tedious. 1. #define `Foo_IVARS` as `Foo` 2. Set Foo_GET_IVARS() to return `self`. 3. Change over all struct access in the Lucy core to use IVARS. 4. Change over Foo_IVARS to be only class-specific member variables. 5. Stop providing struct defs for `Foo`. Marvin Humphrey
