Skip to content

Instantly share code, notes, and snippets.

@mletterle
Created March 24, 2012 01:41
Show Gist options
  • Save mletterle/2177221 to your computer and use it in GitHub Desktop.
Save mletterle/2177221 to your computer and use it in GitHub Desktop.
.assembly Test { }
.class public TestClass
extends [mscorlib]System.Object
{
.method specialname static public void Main() cil managed
{
.entrypoint
newobj instance void AnotherClass2::.ctor()
dup
callvirt instance void AnotherClass::Method(class AnotherClass)
ret
}
}
.class public AnotherClass
extends [mscorlib]System.Object
{
.method specialname rtspecialname public instance void .ctor() cil managed
{
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
.method public void Method(class AnotherClass a) cil managed
{
ldarg.1
call instance string AnotherClass::Something()
call void [mscorlib]System.Console::WriteLine(string)
ret
}
.method public instance string Something() cil managed
{
ldstr "AnotherClass"
ret
}
}
.class public AnotherClass2
extends [mscorlib]System.Object
{
.method specialname rtspecialname public instance void .ctor() cil managed
{
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
}
@keyvan
Copy link

keyvan commented Mar 24, 2012

It's a virtual method dispatch on AnotherClass so it goes on the method table for AnotherClass and finds the corresponding method implementation and executes that. I still don't know what exactly you meant by your original question since AnotherClass2 is totally independent of AnotherClass. dup, of course, duplicates the top item on stack, but again, I don't know what you're exactly looking for.

@mletterle
Copy link
Author

Being an instance method, shouldn't it be using the instance on the top of the stack? This object has a different type then the method signature being called. And the object being passed in is also AnotherClass2, which doesn't match the type of the parameter. I'd expect that the CLR would actually refuse to load the assembly with an Invalid Program exception since it violates the spec for callvirt calls (Correct CIL should have the types matching).

@keyvan
Copy link

keyvan commented Mar 24, 2012

I see your point now. I don't know the specifications of .NET CLR for such a case, but it would make sense if it terminates with error. It could also let it flow and check the method table and then terminate when it can't find the implementation on the object's method table. Did you try to compile it?

@mletterle
Copy link
Author

Oh yes. It doesn't peverify, of course, but it's quite happy to run. It outputs "AnotherClass". It actually does this on both .NET and Mono, which kind of surprised me. Luckily it does sanely break down if you try to save the result of Something() to an instance field. So there's that...

@keyvan
Copy link

keyvan commented Mar 24, 2012

Then it looks like it's following an approach similar to the second case I wrote above. As long as they can pass the method table, they continue flowing.

Did you generate it by hand, or it's a part of a program you're writing. I'm curious to know what scenario this is representing.

@mletterle
Copy link
Author

It's written by hand. Kinda stumbled over the fact that the runtime doesn't actually seem to enforce the type correctness of arguments being passed to methods, and just eventually got here.

@keyvan
Copy link

keyvan commented Mar 24, 2012

Yes, in most languages most of the type checking usually occurs in previous steps of compilation before generating the IL code, so for efficiency reasons of compilation, it's not redone. .NET would be the same.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment