Bug 29636 - Attempting to JIT compile method while running with --aot-only.
Summary: Attempting to JIT compile method while running with --aot-only.
Status: ASSIGNED
Alias: None
Product: iOS
Classification: Xamarin
Component: XI runtime (show other bugs)
Version: master
Hardware: PC Windows
: Normal normal
Target Milestone: Untriaged
Assignee: Zoltan Varga
URL:
Depends on:
Blocks:
 
Reported: 2015-05-01 05:32 UTC by Vladislav Kosev
Modified: 2015-11-05 13:34 UTC (History)
6 users (show)

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


Attachments
A test project for reproduction (8.33 KB, application/octet-stream)
2015-05-01 05:32 UTC, Vladislav Kosev
Details

Description Vladislav Kosev 2015-05-01 05:32:57 UTC
Created attachment 11011 [details]
A test project for reproduction

I get an exception on device (NOT simulator) when wrapping a set method of a property in a delegate and trying to use it. If I try property3.SetValue(instance, DateTime.Now) then it works. If I do:

var setMethod = property.SetMethod;
_setter = (Action<T, U>)setMethod.CreateDelegate(typeof(Action<T, U>));
_setter((T)target, (U)value);

The last line throws an exception:
2015-05-01 12:23:45.365 iOSSetValueTest[248:142495] Attempting to JIT compile method '(wrapper delegate-invoke) <Module>:invoke_callvirt_void_TestClass_Nullable`1<int> (iOSSetValueTest.TestClass,System.Nullable`1<int>)' while running with --aot-only. See http://docs.xamarin.com/ios/about/limitations for more information.
[0:] Attempting to JIT compile method '(wrapper delegate-invoke) <Module>:invoke_callvirt_void_TestClass_Nullable`1<int> (iOSSetValueTest.TestClass,System.Nullable`1<int>)' while running with --aot-only. See http://docs.xamarin.com/ios/about/limitations for more information.
[0:] 
2015-05-01 12:23:45.582 iOSSetValueTest[248:142495]   at iOSSetValueTest.ModelPropertyAccessor`2[iOSSetValueTest.TestClass,System.Nullable`1[System.Int32]].SetValue (System.Object target, System.Object value) [0x0001c] in c:\Users\vkosev\AppData\Local\Temporary Projects\iOSSetValueTest\AppDelegate.cs:117 
  at iOSSetValueTest.AppDelegate.FinishedLaunching (UIKit.UIApplication app, Foundation.NSDictionary options) [0x0012d] in c:\Users\vkosev\AppData\Local\Temporary Projects\iOSSetValueTest\AppDelegate.cs:62 
[0:]   at iOSSetValueTest.ModelPropertyAccessor`2[iOSSetValueTest.TestClass,System.Nullable`1[System.Int32]].SetValue (System.Object target, System.Object value) [0x0001c] in c:\Users\vkosev\AppData\Local\Temporary Projects\iOSSetValueTest\AppDelegate.cs:117 
  at iOSSetValueTest.AppDelegate.FinishedLaunching (UIKit.UIApplication app, Foundation.NSDictionary options) [0x0012d] in c:\Users\vkosev\AppData\Local\Temporary Projects\iOSSetValueTest\AppDelegate.cs:62 

I am unsure if this is actually a bug, but when I spoke to Jon Goldberger from support we decided that this is most likely a bug as it is not code generation.

I have attached a very simple sample project that illustrates the exception. Just run it and it will show the exception. Again, it does NOT happen on the simulator.

Please advise.
Comment 1 Rolf Bjarne Kvinge [MSFT] 2015-05-01 05:40:10 UTC
Zoltan, this looks like one of our limitations, could you confirm this?
Comment 2 Vladislav Kosev 2015-05-01 05:49:40 UTC
If it is indeed a limitation, please explain exactly why it is a limitation and advise on a workaround.

Thanks.
Comment 4 Zoltan Varga 2015-05-01 16:35:36 UTC
The testcase uses a .net feature called open delegates:
http://blog.slaks.net/2011/06/open-delegates-vs-closed-delegates.html
This is not a 100% supported by Xamarin.iOS, for example, it works with primitive types, but not with struct types like int?.

A workaround is to do:

			if (setMethod != null)
				_setter = delegate (T t, U u) {
					var d = (Action<U>)Delegate.CreateDelegate (typeof(Action<U>), t, setMethod);
					d (u);
				};

This has some overhead, as it will create a delegate on every property set/get, so it might or might not be acceptable.
Comment 5 Vladislav Kosev 2015-05-01 16:58:07 UTC
Yea, it beats the point of having delegates in the first place here. The point of this code to not run the full runtime reflection checks every time the set method is called.

Oh well, I came up with another workaround - I wrote a single-file generator that reads the class and creates a partial class with a SetValue(string propertyName, object value) method which has a if/else for all the properties so the can be set dynamically and not use reflection's PropertyInfo.SetValue, which is slow.

Zoltan, can you explain what is the problem with nullable types here? I'm guessing there is a serious reason behind this. Do you plan for this to be fully supported? I know that writing a compiler is some serious engineering. I wonder if project Roslyin (once it is released) will help you with this. I used it to parse the class in the SFG and its great - it gives an absurdly detailed model of the code.

P.S. This is some awesome work guys!! I'm just blown away by the work you've done. I'm super happy to be able to write mobile apps on C#. I know what you're up against and I'm willing to tolerate much more bugs than I usually am. Not gonna spare you the bug reports tho. With some great support I think this is gonna be huge. Cheers!
Comment 6 Vladislav Kosev 2015-05-01 16:59:15 UTC
By the way the project I posted is not sensitive anymore, you can open the bug so others can benefit from this. Thanks anyway Jon!
Comment 7 Vladislav Kosev 2015-05-01 17:10:02 UTC
And it will be nice if this happened on the simulator also. It's a real pain running it on the device to check if I missed something.
Comment 8 Jon Goldberger [MSFT] 2015-05-01 17:14:46 UTC
Setting as public per comment 7 above.

Note You need to log in before you can comment on or make changes to this bug.