Monday, November 22, 2010

How to Detect if a Method is Overridden

Suppose you want to know if (the class of) a particular object overrides a virtual method. For an example of this see OpenJDK's Thread.isCCLOverriden() (line 1573).
In Java the obvious way to do this would be to use reflection. On the CLR there is another way that is both more accurate1 and more efficient.
Here's the MSIL method from IKVM's java.lang.Thread.isCCLOverridden() implementation:

.method private hidebysig static bool isCCLOverridden(class java.lang.Thread A_0) cil managed
{
 ldftn      instance class java.lang.ClassLoader java.lang.Thread::getContextClassLoader()
 ldarg.0
 ldvirtftn  instance class java.lang.ClassLoader java.lang.Thread::getContextClassLoader()
 ceq
 ldftn      instance void java.lang.Thread::setContextClassLoader(class java.lang.ClassLoader)
 ldarg.0
 ldvirtftn  instance void java.lang.Thread::setContextClassLoader(class java.lang.ClassLoader)
 ceq
 and
 ldc.i4.0
 ceq
 ret
}

Instead of running a zillion instructions and accessing a lot of cold data for reflection, this simply leverages the information the JIT already has about virtual methods.

Here's the x86 code this turns into:

 push        ebp
 mov         ebp,esp
 push        esi
 push        ebx
 mov         esi,ecx
 push        258F58h
 mov         ecx,esi
 mov         edx,259240h
 call        JIT_VirtualFunctionPointer
 mov         edx,25DCA0h
 cmp         eax,edx
 sete        bl
 movzx       ebx,bl
 push        2591A0h
 mov         ecx,esi
 mov         edx,259240h
 call        JIT_VirtualFunctionPointer
 mov         edx,25DCB0h
 cmp         eax,edx
 sete        al


Read more: IKVM.NET Weblog