Bug 8448

Summary: `sizeof` IL opcode doesn't behave properly with respect to reference types
Product: [Mono] Runtime Reporter: Jordan Earls <earlz>
Component: JITAssignee: Bugzilla <bugzilla>
Severity: normal CC: mono-bugs+mono, mono-bugs+runtime, vargaz
Priority: ---    
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Tags: Is this bug a regression?: ---
Last known good build:
Attachments: compiled test case
sizeof IL library (required to run example program)

Description Jordan Earls 2012-11-15 21:31:11 UTC
Created attachment 2953 [details]
compiled test case

I believe I've found a bug concerning the `sizeof` opcode in Mono's IL implementation. Note: I'm NOT talking about the C# `sizeof()` operator. 

I made a tiny library in IL that has this method:

    .method public static hidebysig
           default int32 SizeOf<T> ()  cil managed
        .maxstack 1
	sizeof !!T

And then I tested it with:

	class MainClass
		public static void Main (string[] args)
			Console.WriteLine(BareMetal.SizeOf<Bar>()); //THIS
	struct Foo
		int a, b;
		byte c;
		object foo;
	class Bar
		string foo;
		string bar;
		AssemblyLoadEventArgs meh;
		DateTime d;
		byte[] Buffer;
		int mejhf;
		long fjke;
		byte jkfd;
		int fjkd;
		int jfke;

The output from this program is rather surprising for the sizeof Bar. Here is the full output (on my 64-bit machine):


I posted about this issue in the mailing list, but was told to look here: http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.sizeof%28v=vs.95%29.aspx

That link appears to indicate my IL is invalid, but it does verify. I believe that page is flat-out wrong also. In the ECMA spec, on page 423 for partition III, it says "For a reference type, the size returned is the size of a reference value to the corresponding type, not the size of the data stored in objects referred to by a reference value"

Unless Mono is doing some really weird "inlining" of classes into value-types, then Mono is doing it wrong. This can cause a lot of problems because the sizeof opcode was created so that pointer arithmetic with arrays is possible with structures as the elements of the array. 

For reference, on .Net I get the expected value of either 4 or 8 for the size of "Bar" when running the program there (depends on platform of course)
Comment 1 Jordan Earls 2012-11-15 21:31:53 UTC
Created attachment 2954 [details]
sizeof IL library (required to run example program)
Comment 2 Jordan Earls 2012-11-15 21:39:38 UTC
The pages are identical, but here is the link to the actual .Net framework doc(not silverlight): http://msdn.microsoft.com/en-us/library/system.reflection.emit.opcodes.sizeof%28v=vs.110%29.aspx
Comment 3 Zoltan Varga 2012-11-17 04:15:11 UTC
Fixed in master.