Alex Rivera | Logout

Is Richter mistaken when describing the internals of a non-virtual method call?

Asked 2011-02-05T20:11:23.960
13

I would write this question directly to Jeffrey Richter, but last time he didn't answer me :) so I will try to get an answer with your help here, guys :)

In the book "CLR via C#", 3rd edition, on p.108, Jeffrey writes:

void M3() {
  Employee e;
  e = new Manager();
  year = e.GetYearsEmployed();
  ...
}

The next line of code in M3 calls Employee’s nonvirtual instance GetYearsEmployed method. When calling a nonvirtual instance method, the JIT compiler locates the type object that corresponds to the type of the variable being used to make the call. In this case, the variable e is defined as an Employee. (If the Employee type didn’t define the method being called, the JIT compiler walks down the class hierarchy toward Object looking for this method. It can do this because each type object has a field in it that refers to its base type; this information is not shown in the figures.) Then, the JIT compiler locates the entry in the type object’s method table that refers to the method being called, JITs the method (if necessary), and then calls the JITted code.

When I read this first time I thought that it would be not effective to walk along the class hierarchy looking for the method during JIT-ting. It is easy to find the method already on compile stage. But I believed to Jeffrey. I posted this information on another forum and another guy confirmed my doubts that it is strange and would be ineffective and that it seems it is wrong information.

And really, if you look for the corresponding IL code in a decompiler, such as ILDasm or Reflector (I've checked in both) you will see that IL has a callvirt instruction calling the method from the base class, so JIT doesn't need to look in which class the method is located at runtime:

public class EmployeeBase
{
    public int GetYearsEmployed() { return 1; }
}

public
Edit
Report

1 Answer

1

From my understanding, and using your example: Under the hood:

A VIRTUAL method in a base class WILL have an entry in a derived class method table. This means that all the virtual methods in the 'object' type are available in all their derived classes method table.

A NON virtual method (as in the example code), with no supplied functionality in the derived classes will NOT actually have an entry in the derived classes method tables!

To check this, I ran the code in WinDbg to examine the method table for the Manager class.

MethodDesc Table Entry MethodDe JIT Name

506a4960 503a6728 PreJIT System.Object.ToString()

50698790 503a6730 PreJIT System.Object.Equals(System.Object)

50698360 503a6750 PreJIT System.Object.GetHashCode()

506916f0 503a6764 PreJIT System.Object.Finalize()

001b00c8 00143904 JIT Manager..ctor()

0014c065 001438f8 NONE Manager.GenProgressReport()

So,I can see the virtual object methods of object, but I can't see the actual method GetYearsEmployed since it's not virtual and has no derived implementation. Incidentally, by the same concept, you can't see the SomeOtherMethod function in the derived class either.

You can, however, call these functions, it's just they are not there in the method table. I could be incorrect, but I believe the call stack is walked to find them. Maybe this is what Mr Richter means in his book. I find his book difficult to read but that's because the concepts are complicated and he is cleverer than me :)

I'm not sure the IL reflects the problem. I believe it's possibly a layer below IL which is why I've used Windbg to take a look. I suppose you could use windbg to see of it walks the stack....

answered 2013-01-02T18:31:29.173

Your Answer