This is Xamarin's bug tracking system. For product support, please use the support links listed in your Xamarin Account.
Bug 3706 - generics aot jit problem
Summary: generics aot jit problem
Status: RESOLVED FIXED
Alias: None
Product: iOS
Classification: Xamarin
Component: General (show other bugs)
Version: 5.2
Hardware: PC Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Bugzilla
URL:
Depends on:
Blocks:
 
Reported: 2012-03-01 13:55 UTC by Chris Toshok
Modified: 2016-02-11 15:03 UTC (History)
5 users (show)

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


Attachments
AppDelegate.cs file (1.42 KB, text/plain)
2012-03-01 13:55 UTC, Chris Toshok
Details
solution I've been using (7.21 KB, application/x-gzip)
2012-03-03 01:38 UTC, Chris Toshok
Details

Description Chris Toshok 2012-03-01 13:55:45 UTC
Created attachment 1447 [details]
AppDelegate.cs file

The attached AppDelegate.cs (just create a normal single view iphone app and replace that file with the attached) crashes with the usual "Could not JIT method ... full-aot..." with or without INTERNAL_SLOT_STRUCT defined.

Neither case seems like it should crash.  The type info should propagate in such a way that the aot compiler knows that (in the !INTERNAL_SLOT_STRUCT case) it needs an instantiation of Slot<ListObject>, shouldn't it?
Comment 1 Chris Toshok 2012-03-01 14:03:07 UTC
changing CrashMono to the following keeps things from crashing:


		public void CrashMono ()
		{
			List<ListSlot<ListObject>> foo = new List<ListSlot<ListObject>>();
			MyList<ListObject> list = new MyList<ListObject>();
		}

but I'm at a loss for how the mono compiler can't propagate T=ListObject into the instantiation of MyList, and know that List<ListSlot<ListObject>> is required itself.
Comment 2 Zoltan Varga 2012-03-01 19:12:29 UTC
I can't reproduce this with a console test program, neither with master or 2.10.
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
using System;
using System.Collections.Generic;
using System.Linq;

namespace genericsbug
{
	public class Tests {
		public static void Main (String[] args) {
			MyList<ListObject> list = new MyList<ListObject>();
		}
	}
	
	//#if INTERNAL_SLOT_STRUCT
	class ListObject
	{
	}
	
	class MyList<T> where T : ListObject
	{
		protected struct Slot
		{
			T item;
		}
		
		List<Slot> slots = new List<Slot>();
	}
}
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Comment 3 Zoltan Varga 2012-03-02 17:36:20 UTC
I can't repro this with mt 5.2.5 either.
Comment 4 Chris Toshok 2012-03-02 18:24:00 UTC
On device?

it definitely happens here.. 100% of the time...

hrm..  mono version shouldn't matter as monotouch uses all its own stuff.

anything I can do on my end to gather more data?
Comment 5 Zoltan Varga 2012-03-02 19:02:25 UTC
Are you using some special linker flags etc ?
Comment 6 Chris Toshok 2012-03-03 01:35:13 UTC
nope, just a totally vanilla solution.

Let me attach it.
Comment 7 Chris Toshok 2012-03-03 01:38:14 UTC
Created attachment 1456 [details]
solution I've been using
Comment 8 Zoltan Varga 2012-03-03 06:32:54 UTC
I can somewhat reproduce this. I get a runtime assertion in Release|iPhone configuration instead of an exception printed to the application output window.
Comment 9 Zoltan Varga 2012-03-03 06:39:36 UTC
Correction: it only happens in Debug|iHpone configuration, and only if 'Enable debugging' is enabled. Probably the JIT optimizations disabled in debug mode cause this.
Comment 10 Zoltan Varga 2012-03-03 15:12:53 UTC
So the problem happens because of generic sharing. ListObject is a reference type,
so the 	MyList<ListObject> list = new MyList<ListObject>(); call doesn't cause any additional methods to be compiled because MyList<ListObject>.ctor () is generic shared, so it is implemented by MyList<T>.ctor ().
When MyList<T>.ctor () is compiled, it doesn't know about the non-gshared
List<MyList`1/Slot<ListObject>> type which is needed at runtime.
Comment 11 Chris Toshok 2012-03-04 00:31:14 UTC
gsharing isn't turned off in release mode, is it?  is there some other pass that's propagating type info?
Comment 12 Zoltan Varga 2012-03-04 08:51:47 UTC
I can only repro this in Debug mode.
Comment 13 Chris Toshok 2012-03-05 22:09:42 UTC
right.  Just wondering if there's an optimization pass that should be turned on for debug mode so that the code can execute?
Comment 14 Zoltan Varga 2012-03-06 14:15:53 UTC
You can turn on inlining by disabling the code which disables it in mini.c:

                cfg->opt &= ~MONO_OPT_DEADCE;
                //cfg->opt &= ~MONO_OPT_INLINE;
                cfg->opt &= ~MONO_OPT_COPYPROP;
                cfg->opt &= ~MONO_OPT_CONSPROP;
                /* This is no longer needed with sdb */
                //cfg->opt &= ~MONO_OPT_GSHARED;

This will make sdb less usable or not usable at all.
Comment 15 Rodrigo Kumpera 2012-03-06 14:35:25 UTC
Hey Zoltan,

The type List<MyList`1/Slot<T>> can be gshare'able. We should proably should look into how much work it would entail.
Comment 16 Rolf Bjarne Kvinge [MSFT] 2016-02-11 15:03:25 UTC
This works fine now.

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