I was researching call vs callvirt opcodes with all of the gotchas along the way.
You can read the description online, but when you encounter this
The callvirt instruction calls a late-bound method on an object. That is, the method is chosen based on the runtime type of obj rather than the compile-time class visible in the method pointer.
you know it's not the full story since callvirt is emitted for virtually everything by the C# compiler and that the implementation details make up for all the difference.
I think what the callvirt internally does is check the metadata token from the method table for whether it's virtual or not and if not virtual, doesn't really bother with the object's vtables. But how do I know?
Can somebody explain how the runtime code is structured with regard to handling of the opcodes (I guess the JITter) so I can more easily browse the source code and understand the implementation details.