Virtual function call stuff, again
Jason Merrill
jason at cygnus.com
Tue Feb 22 23:40:45 UTC 2000
>>>>> Mark Mitchell <mark at codesourcery.com> writes:
>>>>>> Mark Mitchell <mark at codesourcery.com> writes:
>> o Suppose a class `A' defines a virtual function `A::f'. The
>> primary vtable for `A' contains a pointer to an entry point
>> that performs no adjustment.
>> o Suppose that a class `A' declares a virtual function `A::f',
>> and suppose that `A' is a base class in a hierarchy dominated
>> by another class `B'. Suppose that the unique final overrider for
>> `A::f' in `B' is `C::f'. We must determine what entry point
>> is used for `f' in the `A-in-B' secondary vtable. Here is the
>> algorithm:
Oops; I missed the basic misunderstanding in my previous reply.
Actually, the algorithm for this case is very simple: use the same entry
point as is used in the 'A-in-C' secondary vtable. Since 'B' does not
override 'f', it does not introduce a new entry point. That's the primary
design goal.
So the interesting question is, what do you put in the 'A-in-C' secondary
vtable?
>> - Find any path from `B' to `C' in the inheritance graph for `B'.
...from 'C' to 'A'...for 'C'.
>> - If there is no virtual base along the path, then create
>> an entry point which adjusts the `this' pointer from `A' to `C'.
>> This value can be computed statically when the `A-in-B' vtable
>> is created. Then transfer control to the non-adjusting entry
>> point for `C::f'.
...when the 'A-in-C' vtable is created.
>> - If there is a virtual base along this path, let `V' be the
>> virtual base nearest to `C' along the path. (In fact, `V'
>> will be `C' itself if `C' is a virtual base.)
> Rather, nearest to 'A'.
> How is that defined? We're looking at paths between `B' and `C'. But
> maybe I got that wrong, too?
Yes; see above.
>> (Note that the choice of `V' is independent of the choice of path.
>> If there was more than one path, then there must have been a
>> virtual base along all of the paths, and there is a unique one
>> closest to `C'.)
> No; we're looking for the most-derived base subobject of which our A is a
> non-virtual base, which is unique.
> Something is under-specified there. (We're looking for something that
> is a virtual base, right?) How, exactly, do we find `V'? That's the
> part that still seems most unclear to me.
Walk down the inheritance chain from A to C, and stop when you see the
first use of virtual inheritance.
>> Now, create an entry point which first performs the adjustment
>> from `A' to `V'. (This value can be computed statically, when
>> the `A-in-B' vtable is created.) Then, adjust the `this'
'A-in-C'
>> pointer by the vcall offset stored in the secondary vtable for
>> `V' (i.e., the `V-in-B' vtable). (This adjustment will adjust
>> the `this' pointer from `V' to `C'.) Finally, transfer control
>> to the non-adjusting entry point for `C::f'.
'V-in-B' is correct here. When B is defined, the only thing that needs to
change in the secondary vtable for V is the vcall offset, not the entry
point.
> If C is different from A, but A is the same as V, then we need one entry
> point directly before the main function, which adds the vcall offset and
> falls through.
> If C != A != V, and V overrides f, then we need one more entry point,
> so we get:
> A vtable entry point
> adjusts the A* to a V* by a constant offset and falls through to
> V vtable entry point
> adjusts the V* to a C* by the vcall offset in the vtable and falls
> through to
> C::f
> How does that work if there is more than one `A'? I understand that
> more than one `V' could be handled by having different vcall offsets
> for each `V'.
If there is more than one A, then you can't just fall through, you have to
branch. So you would add (at the beginning of the above):
A1 vtable entry point
adjusts the A1* to a V* by a constant offset and jumps to the V entry point
But you can use a PC-relative branch in this situation, so the performance
hit is small.
> Our first priority is to provide a conforming implementation. I
> expect that will mean that we don't take full advantage of the new
> ABI. But, the good news is that, because it's an ABI, we can take
> more advantage of it later and still link with things produced by
> earlier versions of the compiler.
Fair enough.
Jason
More information about the cxx-abi-dev
mailing list