This is the mail archive of the gcc@gcc.gnu.org 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]
Other format: [Raw text]

Re: Devirtualize virtual call hierarchy if just base dtor exists


On 22 October 2014 17:16, Martin LiÅka <mliska@suse.cz> wrote:
> On 10/22/2014 05:30 PM, Jonathan Wakely wrote:
>>
>> On 22 October 2014 16:15, Martin LiÅka wrote:
>>>
>>> Hello.
>>>
>>> I've been playing with following example:
>>>
>>> #include <stdlib.h>
>>>
>>> class Base
>>> {
>>> public:
>>>    virtual ~Base() {}
>>> };
>>>
>>> class Derived: public Base
>>> {
>>> };
>>>
>>> #define N 1000
>>>
>>> int main()
>>> {
>>>    Base **b = (Base **)malloc (sizeof(Base *) * N);
>>>    for (unsigned i = 0; i < N; i++)
>>>      b[i] = new Derived();
>>>
>>>    for (unsigned i = 0; i < N; i++)
>>>      delete b[i];
>>>
>>>    return 0;
>>> }
>>>
>>> Where I would like to somehow give an advice to devirtualize machinery.
>>> My
>>> motivation is to inline destruction in 'delete b[i]'.
>>> 'final' keyword does not solve my problem:
>>>
>>> a.c:9:7: error: virtual function âvirtual Derived::~Derived()â
>>>   class Derived: public Base
>>>         ^
>>> a.c:6:11: error: overriding final function âvirtual Base::~Base()â
>>>     virtual ~Base() final {}
>>
>>
>> Virtual destructors are special, derived classes *must* override them,
>> so you can't make it final in the base class.
>>
>>> If I enclose my classes to anonymous namespace:
>>>
>>> Procesing function int main()/172
>>>    Targets of polymorphic call of type 0:struct Base token 2
>>>      Contained in type:struct Base at offset 0
>>>      This is a complete list. (derived types included)
>>>         virtual {anonymous}::Base::~Base()/164 virtual
>>> {anonymous}::Derived::~Derived()/183
>>>
>>> More than one likely target
>>
>>
>> Presumably because the dynamic type of *b[i] could be Base or Derived,
>> and the compiler can't know until it checks it. Does it make any
>> difference if you make Base an abstract class? In that case the
>> compiler should know that the dynamic type of *b[i] cannot be Base, so
>> must be a Derived.
>
>
>
> Looks that addition of an abstract method to Base class really helps:
>
>   for (unsigned i = 0; i < N; i++)
>     delete b[i];
>   4006a0:       48 8b 3b                mov    (%rbx),%rdi
>   4006a3:       48 85 ff                test   %rdi,%rdi
>   4006a6:       74 05                   je     4006ad <main+0x4d>
> public:
>   virtual ~Base() {}
>   virtual void Foo() = 0;
> };
>
> class Derived final: public Base
>   4006a8:       e8 83 ff ff ff          callq  400630 <_ZdlPv@plt>
>   4006ad:       48 83 c3 08             add    $0x8,%rbx

Cool, that's what I expected.

However, if you have more than one type that inherits from Base and
either Derived or Derived2 has a non-trivial destructor then it
probably won't help, as the compiler still needs to do a check to see
which destructor to call.

And if you don't have more than derived type why are you using
polymorphism in the first place? i.e. I expect it will only help with
pointless examples, not real code.


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