{"id":3179,"date":"2010-11-05T12:54:00","date_gmt":"2010-11-05T12:54:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/subterranean-il-callvirt-and-virtual-methods\/"},"modified":"2021-04-29T15:30:56","modified_gmt":"2021-04-29T15:30:56","slug":"subterranean-il-callvirt-and-virtual-methods","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/blogs\/subterranean-il-callvirt-and-virtual-methods\/","title":{"rendered":"Subterranean IL: Callvirt and virtual methods"},"content":{"rendered":"<p>Next up is a look at the details of <code>callvirt<\/code> and what happens when you call a virtual method. However, in order to do that, we first need to understand some of the low-level CLR datastructures, and what exactly an object instance is.<\/p>\n<p><b>Object instances<\/b><\/p>\n<p>Object instances are actually suprisingly small and lightweight things &#8211; they comprise of a sync block index used for locking on the object, a pointer to an internal <code>MethodTable<\/code> structure corresponding to the type that this object is an instance of, and the instance fields. That&#8217;s it. Everything else &#8211; method implementations, interfaces, supertype information &#8211; is part of the <code>MethodTable<\/code> structure for the type (this is the structure pointed to by <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.type.typehandle.aspx\"><code>Type.TypeHandle<\/code><\/a>). And, most importantly, within the <code>MethodTable<\/code> structure is stored all the method and interface information used for dynamic method dispatch through <code>callvirt<\/code>.<\/p>\n<p><b>MethodTable<\/b><\/p>\n<p>Within each <code>MethodTable<\/code> structure is a list of all the methods on the type, including inherited methods, in inheritance order. The first entries are always the four virtual methods on <code>System.Object<\/code> (<code>ToString<\/code>, <code>Equals<\/code>, <code>GetHashCode<\/code> and <code>Finalize<\/code>), followed by the virtual methods on the next supertype, and so on, finishing off with virtual and non-virtual methods declared on the type itself. Each entry in the table points to its IL implementation, which can either be its own overriding implementation or the same implementation as its supertype. For example, the following class definitions: <\/p>\n<pre>public class ClassA {\n    public virtual void Method1() { \/* ... *\/ }\n}\npublic class ClassB : ClassA {\n    public virtual void Method2() { \/* ... *\/ }\n}<\/pre>\n<p> will result in <code>MethodTable<\/code> method lists looking something like this: <\/p>\n<pre>|-----------|     |-----------|     |-----------|\n| Object    |     | ClassA    |     | ClassB    |\n|-----------|     |-----------|     |-----------|\n|ToString   |     |ToString   |     |ToString   |\n|Equals     |     |Equals     |     |Equals     |\n|GetHashCode|     |GetHashCode|     |GetHashCode|\n|Finalize   |     |Finalize   |     |Finalize   |\n|-----------|     |Method1    |     |Method1    |\n                  |-----------|     |Method2    |\n                                    |-----------|<\/pre>\n<\/p>\n<p>This means that to <code>callvirt<\/code> <code>ClassA.Method1<\/code> on an object the CLR simply has to follow the method table pointer in the object instance, go to the 5th method table entry, and execute the method pointed to by that entry. This will execute the corresponding implementation for the run-time type of the object.<\/p>\n<p><b>Calling interface methods<\/b><\/p>\n<p>When you implement an interface on a class, the implementing methods are all declared as <code>virtual sealed<\/code>, and therefore will have entries in the <code>MethodTable<\/code> vtable. Mapping an interface method onto it&#8217;s implementation requires a secondary structure called an <code>IVMap<\/code> for each type. This has an entry for each interface known by the system, and each entry points at the implementing methods in the type&#8217;s vtable. Needless to say, the details are quite complicated, change in each version of the CLR, and involve quite a bit of optimization, so I won&#8217;t go into them here. For more details you can read <a href=\"http:\/\/blogs.microsoft.co.il\/blogs\/sasha\/archive\/2007\/02.aspx\">Sasha&#8217;s blog post<\/a> about how the 2.0 CLR does it.<\/p>\n<p><b>Whence <code>callvirt<\/code>?<\/b><\/p>\n<p> It follows that in order to call a method virtually, the <code>this<\/code> pointer on the stack when you call the method has to be of type <code>O<\/code> (heap object reference), as that is the only stack entry type that is guarenteed to have a <code>MethodTable<\/code> pointer through which this dynamic dispatch mechanism can work. Managed pointers (<code>&amp;<\/code>) that <code>call<\/code> can use don&#8217;t have the necessary information to perform the dynamic dispatch.<\/p>\n<p>There is another difference between <code>call<\/code> and <code>callvirt<\/code> &#8211; <code>callvirt<\/code> always checks if the <code>this<\/code> is a null reference, and throws <code>NullReferenceException<\/code> if it is, before calling the method, whereas <code>call<\/code> won&#8217;t thrown a <code>NullReferenceException<\/code> until the <code>this<\/code> pointer is actually accessed using <code>ldarg.0<\/code> within the method. The reason for this should be clear &#8211; if <code>this<\/code> is null, there&#8217;s no <code>MethodTable<\/code> pointer to use to work out the correct run-time method to call!<\/p>\n<p><b>Value types and <code>callvirt<\/code><\/b><\/p>\n<p>An unboxed value type is stored as the concatenation of all its fields, with no sync block index or <code>MethodTable<\/code> pointer. This isn&#8217;t a problem when using <code>call<\/code> as the CLR knows statically which method it should call, so it can simply jump directly to the method implementation. However, you can&#8217;t call a method on a value type using <code>callvirt<\/code> as there&#8217;s no <code>MethodTable<\/code> pointer it can use to figure out the correct method implementation. This is where value type boxing comes in.<\/p>\n<p>To help demonstrate this, I&#8217;m going to use the types from my <a href=\"https:\/\/www.simple-talk.com\/community\/blogs\/simonc\/archive\/2010\/11\/02\/95489.aspx\">previous blog post<\/a>, but with an additional interface: <\/p>\n<pre>public interface IIncrementable {\n    void Increment(int incrementBy);\n}\n\npublic class IncrementableClass : IIncrementable {\n    public int Value;\n    \n    public void Increment(int incrementBy) {\n        Value += incrementBy;\n    }\n}\n\npublic struct IncrementableStruct : IIncrementable {\n    public int Value;\n     \n    public void Increment(int incrementBy) {\n        Value += incrementBy;\n    }\n}<\/pre>\n<\/p>\n<p>If you recall, <code>call<\/code>ing a method on a value type requires a <code>this<\/code> pointer of type <code>&amp;<\/code>. What happens if we simply substitute <code>callvirt<\/code> for the call to <code>IncrementableStruct::Increment<\/code>? <\/p>\n<pre>ldarga 0\nldc.i4.5\ncallvirt instance void IncrementableStruct::Increment(int32)\nret<\/pre>\n<p> As expected, PEVerify doesn&#8217;t like it: <\/p>\n<pre>[offset 0x00000005] Callvirt on a value type method.<\/pre>\n<p>  What about if we call the <code>Increment<\/code> method through the <code>IIncrementable<\/code> interface instead? <\/p>\n<pre>ldarga 0\nldc.i4.5\ncallvirt instance void IIncrementable::Increment(int32)\nret<\/pre>\n<p> Again, PEVerify fails it: <\/p>\n<pre>[offset 0x00000005]\n    [found address of value 'IncrementableStruct']\n    [expected ref 'IIncrementable'] Unexpected type on the stack.\n[offset 0x00000005] Call to base type of valuetype.<\/pre>\n<p> This is all as expected.<\/p>\n<p>To be able to use <code>callvirt<\/code> to call a method on a value type through an interface requires the <code>box<\/code> instruction. This takes a value type from the stack, generates an object instance complete with sync block index and <code>MethodTable<\/code> pointer, and copies the value type bytes into that object. However, the <code>box<\/code> instruction requires the actual value type to be on the stack, rather than the address of the value type, like so (annotated with the stack state): <\/p>\n<pre>.method public static void CallIncrement(        valuetype IncrementableStruct obj) {\nldarg.0                  \/\/ IncrementableStruct\nbox IncrementableStruct  \/\/ O[IncrementableStruct]\nldc.i4.5                 \/\/ O[IncrementableStruct],int32\ncallvirt instance void IIncrementable::Increment(int32)\nret<\/pre>\n<\/p>\n<p><b>So?<\/b><\/p>\n<p>As we&#8217;ve seen, due to how dynamic method dispatch works on .NET, <code>callvirt<\/code> only works when the <code>this<\/code> pointer is of type <code>O<\/code>. To call an interface method on a value type requires the value type to be boxed first, which provides all the necessary information for dynamic dispatch to work. As my next post will detail, this complicates things for generic methods, where the generic type could be a reference or value type at runtime.<\/p>\n<p><a href=\"https:\/\/www.simple-talk.com\/community\/blogs\/simonc\/archive\/2010\/11\/08\/95562.aspx\">Next time<\/a>: finally, generic methods!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Next up is a look at the details of callvirt and what happens when you call a virtual method. However, in order to do that, we first need to understand some of the low-level CLR datastructures, and what exactly an object instance is. Object instances Object instances are actually suprisingly small and lightweight things &#8211;&#8230;&hellip;<\/p>\n","protected":false},"author":186659,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143538,2],"tags":[],"coauthors":[],"class_list":["post-3179","post","type-post","status-publish","format-standard","hentry","category-dotnet-development","category-blogs"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3179","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/186659"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=3179"}],"version-history":[{"count":2,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3179\/revisions"}],"predecessor-version":[{"id":75613,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/3179\/revisions\/75613"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=3179"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=3179"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=3179"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=3179"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}