Bug 6040 - AOT and generics instantiation
Summary: AOT and generics instantiation
Alias: None
Product: Runtime
Classification: Mono
Component: General ()
Version: unspecified
Hardware: PC Linux
: --- normal
Target Milestone: ---
Assignee: Bugzilla
Depends on:
Reported: 2012-07-09 01:19 UTC by Virgile Bello
Modified: 2017-07-11 23:29 UTC (History)
7 users (show)

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

Simple file that reproduce the issue. (532 bytes, text/plain)
2012-07-09 01:19 UTC, Virgile Bello

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 Virgile Bello 2012-07-09 01:19:11 UTC
Created attachment 2175 [details]
Simple file that reproduce the issue.

When using generics with AOT, got a JIT exception. I attached a very simple file reproducing the issue at execution (jit3.cs).
Command to run:  mcs jit3.cs && mono --aot=full,log-generics jit3.exe && mono --full-aot jit3.exe
Error: Unhandled Exception: System.ExecutionEngineException: Attempting to JIT compile method 'B:Test<System.Collections.Generic.KeyValuePair`2<object, object>> ()' while running with --aot-only.

Basically, it seems AOT skips scanning sharable method for actual required methods/types (i.e. if A<T> uses KeyValuePair<T> or even SomeMethod<KeyValuePair<T>>() inside one of its method, it should also be AOTed.

It will work fine as long as T is a struct (not sharable, so it will be scanned) but with a reference type, skipping this scan will result in JIT error.

I made a small patch that fix the behavior:
I am not sure whether what I did is a good way to fix it or not, can someone please review (and merge it if it looks OK)?
It still allow sharable method to be shared (executable size doesn't increase much) but it will still scan them for every used type/methods.
Comment 1 Rodrigo Kumpera 2012-07-09 09:48:11 UTC
You're using the full aot compiler incorrectly. You must explicitly full aot all the dependencies as well.
In this case, mscorlib.
Comment 2 Virgile Bello 2012-07-09 11:01:57 UTC
mscorlib is AOTed. All the rest of my program works fine with AOT except this specific issue that I narrowed in this test, so I don't think mscorlib is the issue here (even tho it might look like it).

Problem is not KeyValuePair<,> itself, but the generic method B::Test<>() which is not AOTed properly when called with KeyValuePair<,> (its instantiation happens within the test, so unrelated to mscorlib).

If I run Mono with log level debug, I get:
Mono: AOT loaded AOT Module for /home/xen/dev/monoinstall/lib/mono/4.5/mscorlib.dll
Mono: AOT FOUND method B:Test<System.Collections.Generic.KeyValuePair`2<int, int>> () [0x7f10298b5340 - 0x7f10298b5358 0x7f10298b6370]
Mono: AOT NOT FOUND: B:Test<System.Collections.Generic.KeyValuePair`2<object, object>> ().

If explained it badly the first time or if I am wrong again I apologize (would be good to know if someone could actually test the code with full AOT and report it working), but just wanted to make sure there was no misunderstanding of the actual problem here (seems unrelated to mscorlib from what I understood).
Comment 3 Virgile Bello 2012-07-09 11:03:20 UTC
BTW, if that helps, I run on linux x64.
Comment 4 Zoltan Varga 2012-07-09 12:42:34 UTC
The AOT compiler never sees B<object> because it uses the shared version instead, so it never sees
A<KeyValuwPair<object, object>> either.
Comment 5 Virgile Bello 2012-07-09 21:36:33 UTC
Yes exactly (with B and A swapped ;p).

That's why I made this patch which still allow codegen to happen for every generics instantiation so that it can gather required dependencies (but still it will only add one sharable instantiation in the actual binary, so it shouldn't grow that mucha, hence the early exit).

Does the approach sound good?

I don't know if going through mini_method_compile for every instantiation could be a performance problem, I wanted this patch to be as small as possible and more proof of concept, so maybe this part could be done differently.
Comment 6 Zoltan Varga 2012-07-10 11:18:13 UTC
This approach could work, but it would slow down compilation since basically every generic method instance would be JITted every time it is referenced, which is not how a compiler should work.
Comment 7 Virgile Bello 2012-07-11 01:55:49 UTC
First of all, I noticed some additional cases that this patch could handle and I am currently fixing them (esp. typeof(), and recursive handling from both generic methods and generic types).
I think I got it working well but I am still testing/reviewing.

Yes I understand it could put a burden on the compilation. However:
- It really makes sense to compile everything that way (it's exactly the same C++ would do with template). Everything need to be properly generated, otherwise there is no guarantee code would work properly.
- Compilation time is still very reasonable even with the new version of my patch. Assemblies still compiles quite quickly (i.e. mscorlib and System.Core, probably the most generic intensive ones, still take less than 1.5 seconds).

Anyway, if that's really a concern, I suppose it could just be made so that this is enabled through a aot flags, like --aot=full,recursive-generics?
Comment 8 Virgile Bello 2012-07-11 02:02:53 UTC
BTW, I also made some changes to support async with AOT, it seems to work fine!
I will provide the patch soon if you are interested (still generate some warnings that I need to fix).

I also noticed another small problem, probably due to covariance/contravariance with IEnumerable. I will create a separate bug report with test case soon.
Comment 9 Rodrigo Kumpera 2017-07-11 23:29:33 UTC
This is no longer an issue with gsharedvt.