Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mono] Using Linq.Expressions on iOS crashes unless interpreter is enabled when migrating from xamarin to .NET #94063

Open
rotanov opened this issue Oct 26, 2023 · 4 comments
Assignees
Milestone

Comments

@rotanov
Copy link

rotanov commented Oct 26, 2023

Description

I'm migrating a multi platform game engine from prior to .NET Core/5/6/7/8 era to .NET7.

The following code is crashing on iOS, unless I use <MtouchInterpreter>-all</MtouchInterpreter>

internal static Func<object, int, object, bool> MakeChecker_Crashing(MethodInfo m)
{
  var pObj = Expression.Parameter(typeof(object));
  var pIndex = Expression.Parameter(typeof(int));
  var pItem = Expression.Parameter(typeof(object));
  var e = Expression.Call(Expression.Convert(pObj, m.DeclaringType), m, pIndex, pItem);
  return Expression.Lambda<Func<object, int, object, bool>>(e, pObj, pIndex, pItem).Compile();
}

The exception is

*** Terminating app due to uncaught exception 'System.ExecutionEngineException', reason: 'Attempting to JIT compile method '(wrapper dynamic-method) bool object:Thunk1ret_Boolean_Object_Int32_Object (System.Func`2<object[], object>,object,int,object)' while running in aot-only mode. See https://docs.microsoft.com/xamarin/ios/internals/limitations for more information.
 (System.ExecutionEngineException)
   at System.Delegate.CreateDelegate(Type , Object , MethodInfo , Boolean , Boolean )
   at System.Reflection.Emit.DynamicMethod.CreateDelegate(Type , Object )
   at System.Dynamic.Utils.DelegateHelpers.CreateObjectArrayDelegateRefEmit(Type , Func`2 )
   at System.Dynamic.Utils.DelegateHelpers.CreateObjectArrayDelegate(Type , Func`2 )
   at System.Linq.Expressions.Interpreter.LightLambda.MakeDelegate(Type )
   at System.Linq.Expressions.Interpreter.LightDelegateCreator.CreateDelegate(IStrongBox[] )
   at System.Linq.Expressions.Expression`1[[System.Func`4[[System.Object, System.Private.CoreLib, Version<…>

However it didn't crash in xamarin-ios prior to .NET7 migration.

Interestingly, the following doesn't crash without interpreter:

public static Func<object, object, bool> MakeChecker_NotCrashing(Type tObj, string methodName)
{
   var fn = tObj.GetMethod(methodName);
   var p = Expression.Parameter(typeof(object));
   var pf = Expression.Parameter(typeof(object));
   var e = Expression.Call(Expression.Convert(p, tObj), fn);
   return Expression.Lambda<Func<object, object, bool>>(e, p, pf).Compile();
}

I've made a repo with repro (see repro steps). The code is in AppDelegate.cs

Enabling interpreter adds to application size, in case of empty project using our game engine it's 4.4Mb which is a lot, considering game project teams are always hitting the wall of Apple's application size limit for metered connections. In such context even 100Kb is a lot.

Side note:

Default single view iOS application grew in size quite considerably, see picture:

image

Reproduction Steps

  1. clone the repo
  2. compile and run xamarin-ios/xamarin-ios.sln on a device (I've used iPhone XR)
  3. observe it's not crashing
  4. compile and run net/net7.sln on a device
  5. notice the crash
  6. uncomment line enabling interpreter in net7.csproj
  7. application no longer crashes

Expected behavior

I'm really not sure if this is an expected breaking change or not.

Actual behavior

The crash.

Regression?

No response

Known Workarounds

No response

Configuration

  • .NET7
  • macOS Sonoma 14.0, intel CPU
  • XCode 15.0
  • iPhoneXR iOS 16.3

Other information

No response

@ghost ghost added the untriaged New issue has not been triaged by the area owner label Oct 26, 2023
@ghost
Copy link

ghost commented Oct 26, 2023

Tagging subscribers to this area: @cston
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

I'm migrating a multi platform game engine from prior to .NET Core/5/6/7/8 era to .NET7.

The following code is crashing on iOS, unless I use <MtouchInterpreter>-all</MtouchInterpreter>

internal static Func<object, int, object, bool> MakeChecker_Crashing(MethodInfo m)
{
  var pObj = Expression.Parameter(typeof(object));
  var pIndex = Expression.Parameter(typeof(int));
  var pItem = Expression.Parameter(typeof(object));
  var e = Expression.Call(Expression.Convert(pObj, m.DeclaringType), m, pIndex, pItem);
  return Expression.Lambda<Func<object, int, object, bool>>(e, pObj, pIndex, pItem).Compile();
}

The exception is

*** Terminating app due to uncaught exception 'System.ExecutionEngineException', reason: 'Attempting to JIT compile method '(wrapper dynamic-method) bool object:Thunk1ret_Boolean_Object_Int32_Object (System.Func`2<object[], object>,object,int,object)' while running in aot-only mode. See https://docs.microsoft.com/xamarin/ios/internals/limitations for more information.
 (System.ExecutionEngineException)
   at System.Delegate.CreateDelegate(Type , Object , MethodInfo , Boolean , Boolean )
   at System.Reflection.Emit.DynamicMethod.CreateDelegate(Type , Object )
   at System.Dynamic.Utils.DelegateHelpers.CreateObjectArrayDelegateRefEmit(Type , Func`2 )
   at System.Dynamic.Utils.DelegateHelpers.CreateObjectArrayDelegate(Type , Func`2 )
   at System.Linq.Expressions.Interpreter.LightLambda.MakeDelegate(Type )
   at System.Linq.Expressions.Interpreter.LightDelegateCreator.CreateDelegate(IStrongBox[] )
   at System.Linq.Expressions.Expression`1[[System.Func`4[[System.Object, System.Private.CoreLib, Version<…>

However it didn't crash in xamarin-ios prior to .NET7 migration.

Interestingly, the following doesn't crash without interpreter:

public static Func<object, object, bool> MakeChecker_NotCrashing(Type tObj, string methodName)
{
   var fn = tObj.GetMethod(methodName);
   var p = Expression.Parameter(typeof(object));
   var pf = Expression.Parameter(typeof(object));
   var e = Expression.Call(Expression.Convert(p, tObj), fn);
   return Expression.Lambda<Func<object, object, bool>>(e, p, pf).Compile();
}

I've made a repo with repro (see repro steps). The code is in AppDelegate.cs

Enabling interpreter adds to application size, in case of empty project using our game engine it's 4.4Mb which is a lot, considering game project teams are always hitting the wall of Apple's application size limit for metered connections. In such context even 100Kb is a lot.

Side note:

Default single view iOS application grew in size quite considerably, see picture:

image

Reproduction Steps

  1. clone the repo
  2. compile and run xamarin-ios/xamarin-ios.sln on a device (I've used iPhone XR)
  3. observe it's not crashing
  4. compile and run net/net7.sln on a device
  5. notice the crash
  6. uncomment line enabling interpreter in net7.csproj
  7. application no longer crashes

Expected behavior

I'm really not sure if this is an expected breaking change or not.

Actual behavior

The crash.

Regression?

No response

Known Workarounds

No response

Configuration

  • .NET7
  • macOS Sonoma 14.0, intel CPU
  • XCode 15.0
  • iPhoneXR iOS 16.3

Other information

No response

Author: rotanov
Assignees: -
Labels:

area-System.Linq.Expressions

Milestone: -

@rotanov rotanov changed the title With .NET7 code using Linq.Expressions on iOS crashes unless interpreter is enabled. It did not crash in xamarin-ios. In .NET7 code using Linq.Expressions on iOS crashes unless interpreter is enabled. It did not crash in xamarin-ios. Oct 26, 2023
@ivanpovazan ivanpovazan self-assigned this Oct 27, 2023
@ivanpovazan ivanpovazan added area-Codegen-AOT-mono os-ios Apple iOS and removed area-System.Linq.Expressions untriaged New issue has not been triaged by the area owner labels Oct 27, 2023
@ivanpovazan ivanpovazan added this to the 9.0.0 milestone Oct 27, 2023
@ghost
Copy link

ghost commented Oct 27, 2023

Tagging subscribers to 'os-ios': @steveisok, @akoeplinger, @kotlarmilos
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

I'm migrating a multi platform game engine from prior to .NET Core/5/6/7/8 era to .NET7.

The following code is crashing on iOS, unless I use <MtouchInterpreter>-all</MtouchInterpreter>

internal static Func<object, int, object, bool> MakeChecker_Crashing(MethodInfo m)
{
  var pObj = Expression.Parameter(typeof(object));
  var pIndex = Expression.Parameter(typeof(int));
  var pItem = Expression.Parameter(typeof(object));
  var e = Expression.Call(Expression.Convert(pObj, m.DeclaringType), m, pIndex, pItem);
  return Expression.Lambda<Func<object, int, object, bool>>(e, pObj, pIndex, pItem).Compile();
}

The exception is

*** Terminating app due to uncaught exception 'System.ExecutionEngineException', reason: 'Attempting to JIT compile method '(wrapper dynamic-method) bool object:Thunk1ret_Boolean_Object_Int32_Object (System.Func`2<object[], object>,object,int,object)' while running in aot-only mode. See https://docs.microsoft.com/xamarin/ios/internals/limitations for more information.
 (System.ExecutionEngineException)
   at System.Delegate.CreateDelegate(Type , Object , MethodInfo , Boolean , Boolean )
   at System.Reflection.Emit.DynamicMethod.CreateDelegate(Type , Object )
   at System.Dynamic.Utils.DelegateHelpers.CreateObjectArrayDelegateRefEmit(Type , Func`2 )
   at System.Dynamic.Utils.DelegateHelpers.CreateObjectArrayDelegate(Type , Func`2 )
   at System.Linq.Expressions.Interpreter.LightLambda.MakeDelegate(Type )
   at System.Linq.Expressions.Interpreter.LightDelegateCreator.CreateDelegate(IStrongBox[] )
   at System.Linq.Expressions.Expression`1[[System.Func`4[[System.Object, System.Private.CoreLib, Version<…>

However it didn't crash in xamarin-ios prior to .NET7 migration.

Interestingly, the following doesn't crash without interpreter:

public static Func<object, object, bool> MakeChecker_NotCrashing(Type tObj, string methodName)
{
   var fn = tObj.GetMethod(methodName);
   var p = Expression.Parameter(typeof(object));
   var pf = Expression.Parameter(typeof(object));
   var e = Expression.Call(Expression.Convert(p, tObj), fn);
   return Expression.Lambda<Func<object, object, bool>>(e, p, pf).Compile();
}

I've made a repo with repro (see repro steps). The code is in AppDelegate.cs

Enabling interpreter adds to application size, in case of empty project using our game engine it's 4.4Mb which is a lot, considering game project teams are always hitting the wall of Apple's application size limit for metered connections. In such context even 100Kb is a lot.

Side note:

Default single view iOS application grew in size quite considerably, see picture:

image

Reproduction Steps

  1. clone the repo
  2. compile and run xamarin-ios/xamarin-ios.sln on a device (I've used iPhone XR)
  3. observe it's not crashing
  4. compile and run net/net7.sln on a device
  5. notice the crash
  6. uncomment line enabling interpreter in net7.csproj
  7. application no longer crashes

Expected behavior

I'm really not sure if this is an expected breaking change or not.

Actual behavior

The crash.

Regression?

No response

Known Workarounds

No response

Configuration

  • .NET7
  • macOS Sonoma 14.0, intel CPU
  • XCode 15.0
  • iPhoneXR iOS 16.3

Other information

No response

Author: rotanov
Assignees: ivanpovazan
Labels:

area-Codegen-AOT-mono, os-ios

Milestone: -

@ivanpovazan ivanpovazan changed the title In .NET7 code using Linq.Expressions on iOS crashes unless interpreter is enabled. It did not crash in xamarin-ios. [mono] Using Linq.Expressions on iOS crashes unless interpreter is enabled when migrating from xamarin to .NET Oct 27, 2023
@ivanpovazan
Copy link
Member

ivanpovazan commented Oct 27, 2023

@rotanov thank you for reporting this issue and providing detailed repro steps.

I managed to reproduce the issue with .NET8-rc2 release as well (for this reason I slightly modified the title).
This looks like the same problem we reported here: #91332 and is related to how we support System.Linq.Expressions library with MonoAOT compiler in .NET.

@ivanpovazan
Copy link
Member

We don't have capacity to address this in .NET 9. Moving to .NET 10

@ivanpovazan ivanpovazan modified the milestones: 9.0.0, 10.0.0 Aug 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants