Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!purdue!decwrl!ucbvax!hplabs!hp-pcd!hplsla!jima From: jima@hplsla.HP.COM (Jim Adcock) Newsgroups: comp.lang.c++ Subject: Re: address of virtual function (revisited) Message-ID: <6590119@hplsla.HP.COM> Date: 10 May 89 18:28:55 GMT References: <904@garya.Solbourne.COM> Organization: HP Lake Stevens, WA Lines: 133 > The design of the "protected interface", which is what I call the > interface between the base class and derived classes, requires > careful consideration. One of C++ strengths is that it provides > flexibility in specifying this interface. Consequently there is an > obligation on the C++ programmer to use the flexibility wisely. I would claim this obligation falls not simply on the programmer, but also on the C++ compiler designer, and on the person [say C ompiler desginer] who turns the intermediate representation into machine code. The C++ programmer should be free to specify flexibility where needed, and the C++ and C compilers should be smart enough not to use that flexibility where not need. Marking a function "virtual" should not be a unilateral declaration for C and/or C++ compilers to generate bad code. > Using C++ I can cause code to be generated as a direct lookup or as > an indirect function call. Perhaps I've overlooked something. If Jim > suggests an alternative kind of code I'll try to figure out a way to > get it generated. I don't see how any amount of optimization in a > compiler can do anything better unless the indirect function call is > speeded up. A machine in which a virtual function call takes 20X a > load is not a machine designed to run C++ code efficiently. > Personally, I think his complaint is with the hardware designers. > Maybe this discussion should be redirected to comp.arch :-) Hell, if hardware designers were forced to design new machines -- -- and customers were forced to buy them -- everytime someone dreamed up a new language -- then even ObjC could run quickly! I have no problem with C++ *the language*, it *can* be efficiently implemented on today's machine -- I just haven't yet seen a C++ compiler that *does* implement major details of the language efficiently. The biggest disappointment so far is unnecessary expansion of inline virtual functions into table lookup + indirect function calls. Again, if one declares a "virtual function" for size inline; if that inline function just returns a value; and if which virtual function needs actually be called can be uniquely determined at compile time -- then one could hope the assembly that gets generated would be: movel a2@,sp@- Whereas, what *I* *always* get, no matter *how* I call a virtual function [from *my* combination of C++/C compilers] is: movel a3@(4),a0 addqw #8,a0 addw a0@,a3 movel a3,sp@- movel a0@(4),a0 jbsr a0@ | | V link a6,#0 movel a6@(8),a0 movel a0@,d0 unlk a6 rts | | V movel d0,sp@- which is 11 assembly instructions rather than one. I am not about to bother trying to count clock cycles associated with these sequences, but my guess is with the greater complexity of the instructions in the second sequence, the higher chance of cache misses, etc, the second sequence is actually about 20X the first [single instruction] sequence. Looking at the second sequence, one sees that really the assembly code generator ought to be smart enough to leave out the link/unlk sequence, and return the value stack relative [unfortunately, most code generators I've seen are reluctant to do this]: movel a3@(4),a0 addqw #8,a0 addw a0@,a3 movel a3,sp@- movel a0@(4),a0 jbsr a0@ | | V movel sp@(8),a0 movel a0@,d0 rts | | V movel d0,sp@- This would save about 20% of the cost. Next, the C++ compiler should be smart enough to recognize the frequent situation where multiple inheritence is not being used: movel a3@(4),a0 jbsr a0@ | | V movel sp@(8),a0 movel a0@,d0 rts | | V movel d0,sp@- This would save about another 20-30% of the cost. Finally, simply declaring a function "virtual" should not "poison" the function, forcing the full table lookup indirect function call sequence returning a single value, when from context the C++ compiler can determine which [inline] virtual function actually needs to be called. So frequently, the code sequence could be reduced to: movel a2@,sp@- In summary, common optimizing "code generators" [C compilers] are not well suited to the unique needs of generating C++ code, and C++ compilers are not giving the code generators particularly good C code to begin with. To really "support" object oriented programming in C++, virtual functions need to be implemented more efficiently. Programmers should not be unnecessarily forced to make functions non-virtual simply because of the inefficiencies of existing C++ front ends or C back ends. Both need to be better.