Bug 3706

Summary: generics aot jit problem
Product: iOS Reporter: Chris Toshok <toshok>
Component: GeneralAssignee: Bugzilla <bugzilla>
Severity: normal CC: j.bugs, kumpera, mono-bugs+monotouch, rolf, vargaz
Priority: ---    
Version: 5.2   
Target Milestone: Untriaged   
Hardware: PC   
OS: Mac OS   
Tags: Is this bug a regression?: ---
Last known good build:
Attachments: AppDelegate.cs file
solution I've been using

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>();
	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.