Bug 52600 - Full AOT: Strange combination of structs, generics, and enums causes runtime failure
Summary: Full AOT: Strange combination of structs, generics, and enums causes runtime ...
Alias: None
Product: Runtime
Classification: Mono
Component: JIT ()
Version: 4.6.0 (C8)
Hardware: All All
: --- normal
Target Milestone: ---
Assignee: Zoltan Varga
Depends on:
Reported: 2017-02-17 11:39 UTC by Antony Male
Modified: 2017-02-19 13:03 UTC (History)
3 users (show)

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

File which reproduces the issue (1.08 KB, text/plain)
2017-02-17 11:39 UTC, Antony Male

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:

Description Antony Male 2017-02-17 11:39:08 UTC
Created attachment 19863 [details]
File which reproduces the issue

This issue was first reported to me under Xamarin.iOS (on the real device only, the simulator is fine). I managed to reproduce and reduce under Mono on Linux, which is why I filed under "Compilers" and "All Hardware / All OS". Please refile if this was a bad assumption.

Please see the attached sample. I've commented the bits that seem to be critical: it seems to be that the AOT can't figure out that a generic method is called with a struct generic type parameter, but only if that generic method references an enum member on the struct.

Steps to reproduce:

    mcs Program.cs
    mono --aot=full Program.exe
    mono --full-aot Program.exe

On my machine, the output is:

    * Assertion at mini-generic-sharing.c:2351, condition `info' not met


      at <unknown> <0xffffffff>
      at Test.TestClass`1<T_INT>.Part1 () <0x00029>
      at Test.Program.Main (string[]) <0x0001f>
      at (wrapper runtime-invoke) object.runtime_invoke_dynamic (intptr,intptr,intptr,intptr) <0x000cc>

    Native stacktrace:

            mono() [0x4b18ff]
            /usr/lib/libpthread.so.0(+0x11080) [0x7f2dc44a3080]
            /usr/lib/libc.so.6(gsignal+0xcf) [0x7f2dc3f1004f]
            /usr/lib/libc.so.6(abort+0x16a) [0x7f2dc3f1147a]
            mono() [0x6666c9]
            mono() [0x66695c]
            mono() [0x666af3]
            mono() [0x4be8ef]
            mono() [0x4b2716]
            /home/antony/test/StateMechanic/src/Test/bin/Debug/mscorlib.dll.so(generic_trampoline_rgctx_lazy_fetch+0x17f) [0x7f2dc178cc6f]

    Debug info from gdb:

    Got a SIGABRT while executing native code. This usually indicates
    a fatal error in the mono runtime or one of the native libraries
    used by your application.

    Aborted (core dumped)

(Disclaimer: when I first tried to reproduce it on my machine, it failed with "Failed to load AOT module '/usr/lib/mono/4.5/mscorlib.dll.so' while running in aot-only mode: not compiled with --aot=full". I manually copied dlls out of /usr/lib/mono/4.5 into my CWD, AOT'd them with --aot=full, and set MONO_PATH to the CWD. I don't believe this has affected the outcome in any way).

For completion, the original (non-reduced) problem produced the following output on Xamarin.iOS (probably incomplete - it was reported by a third party):

    **System.ExecutionEngineException** has been thrown
    Attempting to JiT compile method 'StateMechanic.StateMachine`1<StateMechanic.State>:RequestEver(StateMechanic.EventTransitionInvoker`1<StateMechanic.State>)' while running with --aot-only. See http://docs.xamarin.com/ios/about/limitations for more information

    at StateMechanic.StateMachine`1[TState].StateMechanic.IEventDelegate.RequestEventFireFromEvent (StateMechanic.Event event, EventFireMethod eventFireMethod) [0x0000a] in <filename unknown>:0 
      at StateMechanic.Event.RequestEventFireFromEvent (EventFireMethod eventFireMethod) [0x0000f] in <filename unknown>:0 
      at StateMechanic.Event.Fire () [0x00000] in <filename unknown>:0
Comment 1 Zoltan Varga 2017-02-18 21:44:03 UTC
Fixed in mono master 15a6c8a875281b04b4bcd69c7b330faf0f4a7ace. Thanks for the testcase.
Comment 2 Antony Male 2017-02-18 23:17:51 UTC
Awesome, nice one. Thanks!
Comment 3 Antony Male 2017-02-18 23:31:16 UTC
Is there a sensible workaround, until that fix makes its way into Xamarin.iOS?
Comment 4 Zoltan Varga 2017-02-19 05:22:03 UTC
The workaround is to avoid calls which are made on 'constrained' types, and return enums, like in the testcase:

       public void Part2<TFoo>(TFoo foo) where TFoo : IFoo // <-- Needs to be generic
            Console.WriteLine(foo.Bar); // <-- Needs to reference the enum member from foo
                                        // (if I add an int member and reference that, everything is OK)

Here TFoo can be either a reference or a struct type, since both can implement IFoo, so its a complicated case.
Comment 5 Antony Male 2017-02-19 13:03:33 UTC
OK, so it's the combination of a constrained type and anything which returns an enum which causes the issue. I see, thanks!