Notice (2018-05-24): bugzilla.xamarin.com is now in
Please join us on
Visual Studio Developer Community and in the
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
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.
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.
You're using the full aot compiler incorrectly. You must explicitly full aot all the dependencies as well.
In this case, mscorlib.
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).
BTW, if that helps, I run on linux x64.
The AOT compiler never sees B<object> because it uses the shared version instead, so it never sees
A<KeyValuwPair<object, object>> either.
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.
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.
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?
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.
This is no longer an issue with gsharedvt.