xamarin-macios icon indicating copy to clipboard operation
xamarin-macios copied to clipboard

aot-runtime.c:1579, condition `data' not met

Open jfversluis opened this issue 1 year ago • 1 comments
trafficstars


Issue moved from dotnet/maui#20657

  • Please respond to @arek-corp.

From @arek-corp on Friday, February 16, 2024 10:54:56 PM

Description

I'm trying to improve the performance of my .NET iOS application by enabling AOT and using interpreter only if absolutely needed. I'm using the following syntax in my .csproj file:

<UseInterpreter>true</UseInterpreter>
<MtouchInterpreter>-all,AutoMapper.dll,CommunityToolkit.Mvvm.dll,FluentValidation.dll, and so on </MtouchInterpreter>

However, when I run the on on a device, the app builds successfully without any unusual warnings but immediately crashes with no info on the debugger side. In the device logs I can only see the following line:

error: * Assertion at /Users/runner/work/1/s/src/mono/mono/mini/aot-runtime.c:1579, condition `data' not met

This seems to be related to some issue with loading AOT for specific assembly. I've tried specifying all the assemblies which I can find in my application package (.app) but the app still crashes. At this point I have no idea which DLL the AOT runtime is complaining about since I'm including all DLLs explicitly at the moment in <MtouchInterpreter> tag.

How do I figure out which specific DLL is causing the issue? Is there a way to force Mono to log some extra information in the device log when the crash happens?

Note (probably doesn't matter): this is actually not a MAUI app but a .NET iOS-only app which was migrated from Xamarin.iOS.

Steps to Reproduce

No response

Link to public reproduction project repository

No response

Version with bug

8.0.3 GA

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

iOS

Affected platform versions

No response

Did you find any workaround?

Enabling interpreter globally by omitting <MtouchInterpreter> tag resolves the issue but this means I'm not taking advantage of AOT at all.

Relevant log output

No response

jfversluis avatar Feb 18 '24 16:02 jfversluis


Issue moved from dotnet/maui#20657

  • Please respond to @drasticactions.

From @drasticactions on Saturday, February 17, 2024 9:52:20 AM

Note (probably doesn't matter): this is actually not a MAUI app but a .NET iOS-only app which was migrated from Xamarin.iOS.

This 100% matters, because this repo is for the cross-platform MAUI UI project, and you want the SDK xamarin/xamarin-macios or runtime repos.

CC @rolfbjarne

jfversluis avatar Feb 18 '24 16:02 jfversluis

So if I'm reading this right:

  1. This works:
<UseInterpreter>true</UseInterpreter>
<MtouchInterpreter>all</MtouchInterpreter>
  1. This does not:
<UseInterpreter>true</UseInterpreter>
<MtouchInterpreter>-all</MtouchInterpreter>
  1. And neither does this:
<UseInterpreter>true</UseInterpreter>
<MtouchInterpreter>-all,AssemblyA.dll,AssemblyB.dll,(all-other-assemblies...)</MtouchInterpreter>

For the next step I'd take note of the fact that you can also enable all, then disable on a per-assembly basis.

So something like this:

<UseInterpreter>true</UseInterpreter>
<MtouchInterpreter>all,-AssemblyA.dll</MtouchInterpreter>

And then trying the assemblies one-by-one to figure out which one causes the problem.

rolfbjarne avatar Feb 19 '24 07:02 rolfbjarne

@rolfbjarne You're right about 1, 2 and 3.

I've also tried the last option you provided, with all assemblies from my package excluded explicitly. The app surprisingly works! Now what I don't understand is what exact assembly the runtime is complaining about.

To get the list of assemblies, I just opened the application package bin/Debug/net8.0-ios/ios-arm64/xxx.app and listed all files with .dll extension. I've also tried running the app with interpreter enabled and firing AppDomain.GetAssemblies() to get all loaded assemblies to include them in MtouchInterpreter tag later. This didn't work as well, it looks like I'm still missing some assembly.

arek-corp avatar Feb 19 '24 07:02 arek-corp

@rolfbjarne I think I got one step further. So it appears due to enabled Linker my .dll list was not complete when I pulled it from .app container. The list included in the build folder instead seems to be comprehensive.

Nevertheless I'm confused about the way UseInterpreter/MtouchInterpreter config works. When I tried to run the app with the following config on a physical device in DEBUG:

<UseInterpreter>true</UseInterpreter>
<MtouchInterpreter>-all,AssemblyA.dll,AssemblyB.dll,(all-other-assemblies...)</MtouchInterpreter>

I got the following crash on start up: Attempting to JIT compile method '(wrapper managed-to-native) bool System.Reflection.RuntimeMethodInfo:get_IsGenericMethod

On my interpreter-included assembly list I had Microsoft.iOS.dll and System.Runtime.dll listed, so I would assume this assembly would be interpreted. Additionally, any assembly NOT listed should be AOT-compiled because I'm deploying on a physical device. Not sure why JIT would step in here at all.

Similarly, tried to run the app on a x86/x64 simulator in DEBUG with the following config:

<UseInterpreter>true</UseInterpreter>
<MtouchInterpreter>-all</MtouchInterpreter>

Also got a crash immediately on start up: error: * Assertion at /Users/runner/work/1/s/src/mono/mono/mini/aot-runtime.c:2490, condition assm->image->aot_module' not met`

It seems like excluding all assemblies from interpreter makes the runtime think the assemblies should be AOT-compiled while they're not since I'm running on the simulator.

What would help is a guidance how UseInterpreter/MtouchInterpreter affects build output in the context of different build configurations (Debug vs Release) and target platforms (x86/x64 simulator vs physical device or ARM64 simulator).

arek-corp avatar Feb 19 '24 13:02 arek-corp

What would help is a guidance how UseInterpreter/MtouchInterpreter affects build output in the context of different build configurations (Debug vs Release) and target platforms (x86/x64 simulator vs physical device or ARM64 simulator).

  1. You can skip UseInterpreter if you set MtouchInterpreter (UseInterpreter=true is equivalent to MtouchInterpreter=all, but MtouchInterpreter takes precedence over any UseIntepreter value).
  2. MtouchInterpreter only makes sense when the AOT compiler is used. For iOS, this only means device + arm64 simulator - on x64 simulator the behavior is undefined (aka it crashes, as you've found out).
  3. There should be no difference between Debug and Release configurations (although in Debug the debugger may be present, which means a bigger potential for bugs - but in theory any MtouchInterpreter value should work with the debugger as well).

Not sure why JIT would step in here at all.

The message "Attempting to JIT compile method ..." means that the app tried to execute a method that wasn't AOT-compiled, and since there's no JIT compiler, the app crashes. That said, I believe the interpreter should step in in this case, so it sounds like a bug.

rolfbjarne avatar Feb 19 '24 18:02 rolfbjarne

  1. You can skip UseInterpreter if you set MtouchInterpreter (UseInterpreter=true is equivalent to MtouchInterpreter=all, but MtouchInterpreter takes precedence over any UseIntepreter value).

Thanks for clarification!

  1. MtouchInterpreter only makes sense when the AOT compiler is used. For iOS, this only means device + arm64 simulator - on x64 simulator the behavior is undefined (aka it crashes, as you've found out).

Well, we 'accidentally' enabled interpreter globally in our app for all kinds of builds and x64 simulator worked but the performance was terrible. CPU-bound operations (like rendering images from PDF file) took 2-2.5 times longer.

I think when Interpreter is enabled and MtouchInterpreter list specified, the fallback is always AOT. So I guess it's either all-or-nothing choice for JIT-compatible targets.

  1. There should be no difference between Debug and Release configurations (although in Debug the debugger may be present, which means a bigger potential for bugs - but in theory any MtouchInterpreter value should work with the debugger as well).

Understood. I think the misleading part is what was described in MAUI ticket https://github.com/dotnet/maui/issues/13019 because it says Interpreter is enabled by default for all Debug builds.

From my testing for .NET iOS (native, not MAUI) it appears however that it's not enabled for any targets/configurations by default. I guess this is by design but it would be good to specify this explicitly somewhere in the docs.

Not sure why JIT would step in here at all.

The message "Attempting to JIT compile method ..." means that the app tried to execute a method that wasn't AOT-compiled, and since there's no JIT compiler, the app crashes. That said, I believe the interpreter should step in in this case, so it sounds like a bug.

Our project is very large (500k lines of code) and I cannot provide an isolated example for this issue unfortunately. At this point we decided to keep Interpreter enabled entirely (without MtouchInterpreter argument) for physical devices, and for ARM64 simulator with the following syntax: <UseInterpreter Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)' == 'arm64'">true</UseInterpreter>

Thanks for the help and input.

arek-corp avatar Feb 20 '24 15:02 arek-corp

Understood. I think the misleading part is what was described in MAUI ticket dotnet/maui#13019 because it says Interpreter is enabled by default for all Debug builds.

From my testing for .NET iOS (native, not MAUI) it appears however that it's not enabled for any targets/configurations by default. I guess this is by design but it would be good to specify this explicitly somewhere in the docs.

Ah I see, It's MAUI who enables the interpreter by default for Debug builds (I believe it's required for Hot Reload).

Plain .NET iOS projects without MAUI don't.

Our project is very large (500k lines of code) and I cannot provide an isolated example for this issue unfortunately. At this point we decided to keep Interpreter enabled entirely (without MtouchInterpreter argument) for physical devices, and for ARM64 simulator with the following syntax: <UseInterpreter Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture)' == 'arm64'">true</UseInterpreter>

OK, understood, I'll close this then.

If you at any point would like us to investigate more, please provide a test project, and we'll have a look.

rolfbjarne avatar Feb 20 '24 15:02 rolfbjarne