Bug 25717 - Calling a created delegate for value type fails in Mono but works in Windows
Summary: Calling a created delegate for value type fails in Mono but works in Windows
Status: RESOLVED FIXED
Alias: None
Product: Runtime
Classification: Mono
Component: JIT ()
Version: unspecified
Hardware: PC Linux
: --- normal
Target Milestone: ---
Assignee: Zoltan Varga
URL:
: 25716 ()
Depends on:
Blocks:
 
Reported: 2015-01-05 12:34 UTC by sornakumar
Modified: 2015-04-16 15:10 UTC (History)
3 users (show)

Tags:
Is this bug a regression?: ---
Last known good build:

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.


Please create a new report on GitHub or Developer Community with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:
Status:
RESOLVED FIXED

Description sornakumar 2015-01-05 12:34:49 UTC
[Unable to add attachment to 25716. Hence opening this bug]

I am trying to create a static property getter for a property in my value type.
Please see the attached file for a sample. When I call the created getter, it
throws the following exception in Mono:

System.NullReferenceException: Object reference not set to an instance of an
object
  at System.IO.TextWriter.Write (System.Object value) [0x00000] in <filename
unknown>:0 
  at System.IO.TextWriter.WriteLine (System.Object value) [0x00000] in
<filename unknown>:0 
  at System.IO.SynchronizedWriter.WriteLine (System.Object value) [0x00000] in
<filename unknown>:0 
  at System.Console.WriteLine (System.Object value) [0x00000] in <filename
unknown>:0 
  at MvcProgram.PropertyHelper.Main () [0x00000] in <filename unknown>:0 
[ERROR] FATAL UNHANDLED EXCEPTION: System.NullReferenceException: Object
reference not set to an instance of an object
  at System.IO.TextWriter.Write (System.Object value) [0x00000] in <filename
unknown>:0 
  at System.IO.TextWriter.WriteLine (System.Object value) [0x00000] in
<filename unknown>:0 
  at System.IO.SynchronizedWriter.WriteLine (System.Object value) [0x00000] in
<filename unknown>:0 
  at System.Console.WriteLine (System.Object value) [0x00000] in <filename
unknown>:0 
  at MvcProgram.PropertyHelper.Main () [0x00000] in <filename unknown>:0 

This however works without any issues in Windows. I am guessing this is a bug
in CreateDelegate.

Thanks.

--- Attached File: (In case you are not able to see the attached file)
using System;
using System.Collections.Concurrent;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Reflection;

namespace MvcProgram
{
    internal class PropertyHelper
    {
    	public struct Test
    	{
    	    public string MyProp {get; set;}
    	    public string StringProp {get; set;}
    	}
    	
    	public static void Main()
        {
    	    Test tt = new Test { MyProp = "1", StringProp = "Hello" };
    	    var prop1 = MakeFastPropertyGetter(typeof(Test).GetProperty("MyProp"));
    	    var prop2 = MakeFastPropertyGetter(typeof(Test).GetProperty("StringProp"));
    	    

    	    Console.WriteLine(prop1(tt));
    	    Console.WriteLine(prop2(tt));
    	}

        // Delegate type for a by-ref property getter
        private delegate TValue ByRefFunc<TDeclaringType, TValue>(ref TDeclaringType arg);

        private static readonly MethodInfo CallPropertyGetterByReferenceOpenGenericMethod =
            typeof(PropertyHelper).GetTypeInfo().GetDeclaredMethod("CallPropertyGetterByReference");

        public static Func<object, object> MakeFastPropertyGetter(PropertyInfo propertyInfo)
        {
            var getMethod = propertyInfo.GetMethod;
            
            var typeInput = getMethod.DeclaringType;
            var typeOutput = getMethod.ReturnType;

            Delegate callPropertyGetterDelegate;
            var delegateType = typeof(ByRefFunc<,>).MakeGenericType(typeInput, typeOutput);
            var propertyGetterAsFunc = getMethod.CreateDelegate(delegateType);

            var callPropertyGetterClosedGenericMethod =
               CallPropertyGetterByReferenceOpenGenericMethod.MakeGenericMethod(typeInput, typeOutput);

            callPropertyGetterDelegate =
                callPropertyGetterClosedGenericMethod.CreateDelegate(
                   typeof(Func<object, object>), propertyGetterAsFunc);

            return (Func<object, object>)callPropertyGetterDelegate;
        }

        // Called via reflection
        private static object CallPropertyGetterByReference<TDeclaringType, TValue>(
            ByRefFunc<TDeclaringType, TValue> getter,
            object target)
        {
            var unboxed = (TDeclaringType)target;
            return getter(ref unboxed);
        }
    }
}
Comment 1 Marek Safar 2015-04-14 10:43:19 UTC
*** Bug 25716 has been marked as a duplicate of this bug. ***
Comment 2 Marek Safar 2015-04-15 07:09:17 UTC
This looks like jit issue.

Comparing prop2 (tt) with null returns false but calling any instance on it throws NRE
Comment 3 Zoltan Varga 2015-04-16 15:10:40 UTC
Fixed in mono master c73363cee456b32c726ef7a0c4d504f1d07eaad2.