This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: [C++ PATCH] ctor vtable vcall offsets

>>>>> "Nathan" == Nathan Sidwell <> writes:

[ABI folks: We've been discussing whether or not the example in 5.2.6,

  struct A { virtual void f(); };
  struct B : virtual public A { int i; };
  struct C : virtual public A { int j; };
  struct D : public B, public C {};

actually requires a third-party thunk.  I say it doesn't, since 3.2.4 says
to call through a C* we must first convert to A*.  Nathan says we should
just call through C's copy of the A vtable, saving the adjustment but
requiring an additional, third-party thunk.  Mark was saying the same
thing, but I appear to have convinced him.]

> Mark Mitchell wrote:

>>[I thought the advantages of taking a primary virtual base were]
>> - Space (because we don't have to have another vptr)
>> - Time (because we don't have to convert to the virtual base to
>> do a virtual call)

> This was my understanding too. I thought the primary motivation for the
> nearly-empty virtual base optimization was for things like Java interfaces
> which are such objects (or their equivalent in a C++ heirarchy).

But with Java interfaces we can assume no adjustment is necessary, since no
adjustment is ever necessary.  With C++ virtual bases, we can't.

> Indeed the
> ABI doc says as rationale in 2.4 II

> 	In case (2b) above, the use of the first indirect primary base
> 	class as the derived class' primary base does not save any space in
> 	the object, and will cause some duplication of virtual function
> 	pointers in the additional copy of the base classes virtual
> 	table. The benefit is that using the derived class virtual pointer
> 	as the base class virtual pointer will often save a load, and no
> 	adjustment to the this pointer will be required for calls to its
> 	virtual functions

Hmm, this does seem contradictory.  I suspect that people weren't thinking
through the ramifications.  In fact, looking back over discussions, I think
this was my fault; in mail from January of 2000 I suggested this sharing,
making the same assumption I'm disagreeing with now.  I even claimed that
converting to a primary virtual base would be a NOP in general.  Mea culpa.

Anyway, my preference would be to change this bit, so that if all our
nearly empty virtual bases are already indirect primary bases, we just give
ourselves a new vtable (as Coleen had suggested in the message to which my
erroneous mail was a response).

Or we could just leave everything as is.  Is anyone from Compaq still on
the list?  Have you (or anyone else) implemented this?  Who's still working
on ABI-compliant compilers, anyway?

> Also,
>     3.2.4 Caller

>    When calling a virtual function f, through a pointer of static type
>    B*, the caller
>      * Selects a (possibly improper) subobject A of B such that A
>        declares f. (In general, A may be the same as B.) (Note that A
>        need not define f; it may contain either a definition of f, or a
>        declaration of f as a pure virtual function.)
> What does 'improper base' mean here? There's no definition of that term.
> I took it to mean this virtual primary base thing which might have been
> lost to some other class in the heirarchy, but our vtable still has
> the right bits in it.

I assume it means that A may not be a proper base of B; that is, it may be
B itself.  Since that is also said by the second parenthetical note, the
first should probably be removed.

Note that the conversion language has been in the description all along.
It seems that Mark questioned it back in Feb 2000, but nobody responded to
him (on the list, anyway).

> Jason Merrill wrote:
>> The main problem with third-party thunks is the time penalty for the
>> indirect branch; that's why we've tried so hard to avoid requiring any.

> By indirect branch you mean you call the thunk which then has to branch
> to the function as it can't be laid out just before hand?

I'm sorry, my terminology was sloppy.  You always get the indirect branch
in virtual function calls, and the resulting misprediction penalty.

Third-party thunks have an additional penalty due to non-locality; in
addition to the cache issues, the direct branch from the thunk to the
function will also be mispredicted.  Thunks emitted with the function can
use pc-relative forward branches or just fall through into the function,
resulting in a much lower penalty.

> If so, you *only* get that constraint on the thunk layout within heirarchies
> that have lost a primary virtual base.


> Now, as Mark says, adjusting to the virtual base might well be a waste of
> time, if the function had been overridden further down the hierarchy - in
> that case, the overrider will have emitted vcall adjusting thunks for all
> the base vtables which contain the entry.

Yes, but if it isn't overridden, going through the thunk you propose is
also a waste of time--and a *lot* more time than the adjustment in the
caller, which can often be scheduled away.

> As those can be emitted with the overriding function, they can run into
> that function have no second branch. If the function is not overridden
> down the heirarchy, then we have to have a vcall adjusting thunk which
> adjusts the this pointer to the real instance of the virtual base within
> the dynamic type of the object. The possibility of that thunk's existance
> known as soon as we have a class with a virtual primary base.  It can be
> emitted once there, but not sooner.

> Now back to the Java interface case. Interfaces have no implementation, so
> the virtual functions must be overridden in the class inheriting the
> interface - so the second half previous paragraph does not apply. That part
> can only apply in C++, and I believe it to be a sufficiently rare case as to
> not be a valid reason to forego the time saving the nearly empty
> virtual base class optimization gives you in the usual case.

And I believe the time savings you mention are not significant enough to
justify complicating the implementation to deal with this special case,
especially given the problems with third-party thunks.


P.S. Weren't we going to move the ABI stuff over to CodeSourcery?

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]