Check out the new USENIX Web site. next up previous
Next: Assembly Code Up: Performance Previous: Branching and Method Calls

Virtual Methods

Implementing virtual methods usually means an extra memory access before the call to the method. This sounds like a performance problem, but in fact it turns out to be a useful optimization, when used wisely.

A call to a C++ virtual method is often used to invoke a context-specific behavior. For example, one might use virtual methods to perform I/O on an abstract class Device. The typical C equivilent is to keep function pointers in a function, and use those function pointers to perform the operation.

The typical C code has the function pointers in the structure with the other variables, making the structure larger. Every instance has pointers to all the functions, so there are many pointers to every function. A more efficient way to do this is to keep in the structure only a pointer to a set of functions. Thus, the structure has only one pointer to represent the behavior functions.

C++ compilers do this automatically. The virtual table is generated by the compiler for each type, and placed in constant memory. Here is an example, for the i960, of a call to a virtual method following a pointer in sfoo:

      ld     _sfoo,g5
      ld     8(g5),g4
      ldis   8(g4),g0
      ld     12(g4),g4
      addo   g5,g0,g0
      callx  (g4)

This generated code loads into g4 the pointer to the function to be execute, and into g0 the pointer to the object. The external pointer variable ``sfoo'' contains the pointer to the object to be manipulated, and the virtual method takes no parameters. With carefully crafted C code, the programmer can save maybe one instruction here.

Obviously, however, this code is far too much to use for acessor methods, such as ``Foo::value()'' above. Although the virtual method performs a useful function efficiently, it is clearly too expensive for trivial functions. The common technique of creating a virtual method that returns a constant value to reveal the true object type is inefficient. If you must do this, run time type information is more practical.

One unexpected benefit of virtual methods is that in certain cases the compiler can tell a priori which implementation of a virtual method applies, and can optimize all the above away, as in:

      ld       _sfoo,g0
      ld       _sfoo+4,g4
      cmpible  g4,g0,L4
      mov      g4,g0
L4:

In this example, ``sfoo'' is an object and not a pointer. C++ knows exactly which implementation applies, and took the liberty of implementing the method inline. The only difference between this and the previous example is that ``sfoo'' is known exactly to be of type Foo.


next up previous
Next: Assembly Code Up: Performance Previous: Branching and Method Calls

Stephen Williams
Sun May 4 15:28:26 PDT 1997