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] expression Cannot box IsByRefLike type 'System.ReadOnlySpan`1' #98805

Open
srxqds opened this issue Feb 22, 2024 · 17 comments
Open

[mono] expression Cannot box IsByRefLike type 'System.ReadOnlySpan`1' #98805

srxqds opened this issue Feb 22, 2024 · 17 comments

Comments

@srxqds
Copy link
Contributor

srxqds commented Feb 22, 2024

Description

we are using Spanjson on ios use interp mode, it will throw exception when use expression generate deserialize/serialize code

Reproduction Steps

our source code:

internal class SpanJson
	{
		/// <summary>
		/// 一个简单的SpanJson测试用例
		/// </summary>
		[Test("SpanJson.SimpleSample")]
		public static void Run()
		{
			Person person = new Person { Name = "John Doe", Age = 30 };

			//Utf16
			{
				//Generic
				{
					var json = JsonSerializer.Generic.Utf16.Serialize(person);
					var deserializeData = JsonSerializer.Generic.Utf16.Deserialize<Person>(json);
					TestUtility.Check(deserializeData.Name == person.Name && deserializeData.Age == person.Age);
				}

				//NonGeneric
				{
					var json = JsonSerializer.NonGeneric.Utf16.Serialize(person);
					var deserializeData = JsonSerializer.NonGeneric.Utf16.Deserialize(json, typeof(Person)) as Person;
					TestUtility.Check(deserializeData.Name == person.Name && deserializeData.Age == person.Age);
				}
			}

			//Utf8
			{
				//Generic
				{
					var bytes = JsonSerializer.Generic.Utf8.Serialize(person);
					var deserializeData = JsonSerializer.Generic.Utf8.Deserialize<Person>(bytes);
					TestUtility.Check(deserializeData.Name == person.Name && deserializeData.Age == person.Age);
				}

				//NonGeneric
				{
					var bytes = JsonSerializer.NonGeneric.Utf8.Serialize(person);
					var deserializeData = JsonSerializer.NonGeneric.Utf8.Deserialize(bytes, typeof(Person)) as Person;
					TestUtility.Check(deserializeData.Name == person.Name && deserializeData.Age == person.Age);
				}
			}
		}
	}

	[JsonFormatterGenerator]
	public class Person
	{
		public string Name { get; set; }
		public int Age { get; set; }
	}

Expected behavior

walk correctly

Actual behavior

throw exception, the stacktrace show below:

···
Exception Test Name: SpanJson.SimpleSample
Cannot box IsByRefLike type 'System.ReadOnlySpan`1'
   at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure, Boolean allowClosed) in System.Private.CoreLib.dll:token 0x6000258+0x86
   at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure) in System.Private.CoreLib.dll:token 0x6000256+0x0
   at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method) in System.Private.CoreLib.dll:token 0x600026d+0x0
   at System.Reflection.Emit.DynamicMethod.CreateDelegate(Type delegateType, Object target) in System.Private.CoreLib.dll:token 0x6005d6b+0x11
   at System.Dynamic.Utils.DelegateHelpers.CreateObjectArrayDelegateRefEmit(Type delegateType, Func`2 handler) in System.Linq.Expressions.dll:token 0x6001038+0x355
   at System.Dynamic.Utils.DelegateHelpers.CreateObjectArrayDelegate(Type delegateType, Func`2 handler) in System.Linq.Expressions.dll:token 0x600102d+0x2
   at System.Linq.Expressions.Interpreter.LightLambda.MakeDelegate(Type delegateType) in System.Linq.Expressions.dll:token 0x6000c1c+0x31
   at System.Linq.Expressions.Interpreter.LightDelegateCreator.CreateDelegate(IStrongBox[] closure) in System.Linq.Expressions.dll:token 0x6000c19+0x0
   at System.Linq.Expressions.Interpreter.LightDelegateCreator.CreateDelegate() in System.Linq.Expressions.dll:token 0x6000c18+0x0
   at System.Linq.Expressions.Expression`1[[SpanJson.JsonSerializer.NonGeneric.Inner`2.DeserializeDelegate[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver`1[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].Compile() in System.Linq.Expressions.dll:token 0x6000641+0x3
   at SpanJson.JsonSerializer.NonGeneric.Inner`2[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver`1[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].BuildDeserializer(Type type) in G:\MonoGroup\spanjson\SpanJson\JsonSerializer.NonGeneric.cs:line 233
   at SpanJson.JsonSerializer.NonGeneric.Inner`2[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver`1[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].BuildInvoker(Type type) in G:\MonoGroup\spanjson\SpanJson\JsonSerializer.NonGeneric.cs:line 160
   at SpanJson.JsonSerializer.NonGeneric.Inner`2.<>c[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver`1[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].<InnerSerializeToString>b__2_0(Type x) in G:\MonoGroup\spanjson\SpanJson\JsonSerializer.NonGeneric.cs:line 44
   at System.Collections.Concurrent.ConcurrentDictionary`2[[System.Type, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.JsonSerializer.NonGeneric.Inner`2.Invoker[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver`1[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].GetOrAdd(Type key, Func`2 valueFactory) in System.Collections.Concurrent.dll:token 0x60000d1+0x47
   at SpanJson.JsonSerializer.NonGeneric.Inner`2[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver`1[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].InnerSerializeToString(Object input) in G:\MonoGroup\spanjson\SpanJson\JsonSerializer.NonGeneric.cs:line 44
   at SpanJson.JsonSerializer.NonGeneric.Utf16.Serialize[ExcludeNullsOriginalCaseResolver`1](Object input) in G:\MonoGroup\spanjson\SpanJson\JsonSerializer.NonGeneric.cs:line 416
   at SpanJson.JsonSerializer.NonGeneric.Utf16.Serialize(Object input) in G:\MonoGroup\spanjson\SpanJson\JsonSerializer.NonGeneric.cs:line 346
   at UnrealEngine.Game.Tests.SpanJson.SpanJson.Run() in /Users/game-netease/unrealmono/UEDemo-427/UEDemo/Content/Script/Game/Tests/SpanJson/SpanJson.cs:line 27
···

Regression?

we have only try use on .net7, but I think .net8 also have this problem.

Known Workarounds

no

Configuration

ios

Other information

No response

@ghost ghost added the untriaged New issue has not been triaged by the area owner label Feb 22, 2024
@jeffschwMSFT jeffschwMSFT added the os-ios Apple iOS label Feb 22, 2024
@ghost
Copy link

ghost commented Feb 22, 2024

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

Issue Details

Description

we are using Spanjson on ios use interp mode, it will throw exception when use expression generate deserialize/serialize code

Reproduction Steps

our source code:

internal class SpanJson
	{
		/// <summary>
		/// 一个简单的SpanJson测试用例
		/// </summary>
		[Test("SpanJson.SimpleSample")]
		public static void Run()
		{
			Person person = new Person { Name = "John Doe", Age = 30 };

			//Utf16
			{
				//Generic
				{
					var json = JsonSerializer.Generic.Utf16.Serialize(person);
					var deserializeData = JsonSerializer.Generic.Utf16.Deserialize<Person>(json);
					TestUtility.Check(deserializeData.Name == person.Name && deserializeData.Age == person.Age);
				}

				//NonGeneric
				{
					var json = JsonSerializer.NonGeneric.Utf16.Serialize(person);
					var deserializeData = JsonSerializer.NonGeneric.Utf16.Deserialize(json, typeof(Person)) as Person;
					TestUtility.Check(deserializeData.Name == person.Name && deserializeData.Age == person.Age);
				}
			}

			//Utf8
			{
				//Generic
				{
					var bytes = JsonSerializer.Generic.Utf8.Serialize(person);
					var deserializeData = JsonSerializer.Generic.Utf8.Deserialize<Person>(bytes);
					TestUtility.Check(deserializeData.Name == person.Name && deserializeData.Age == person.Age);
				}

				//NonGeneric
				{
					var bytes = JsonSerializer.NonGeneric.Utf8.Serialize(person);
					var deserializeData = JsonSerializer.NonGeneric.Utf8.Deserialize(bytes, typeof(Person)) as Person;
					TestUtility.Check(deserializeData.Name == person.Name && deserializeData.Age == person.Age);
				}
			}
		}
	}

	[JsonFormatterGenerator]
	public class Person
	{
		public string Name { get; set; }
		public int Age { get; set; }
	}

Expected behavior

walk correctly

Actual behavior

throw exception, the stacktrace show below:
···
Exception Test Name: SpanJson.SimpleSample
Cannot box IsByRefLike type 'System.ReadOnlySpan1' at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure, Boolean allowClosed) in System.Private.CoreLib.dll:token 0x6000258+0x86 at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure) in System.Private.CoreLib.dll:token 0x6000256+0x0 at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method) in System.Private.CoreLib.dll:token 0x600026d+0x0 at System.Reflection.Emit.DynamicMethod.CreateDelegate(Type delegateType, Object target) in System.Private.CoreLib.dll:token 0x6005d6b+0x11 at System.Dynamic.Utils.DelegateHelpers.CreateObjectArrayDelegateRefEmit(Type delegateType, Func2 handler) in System.Linq.Expressions.dll:token 0x6001038+0x355
at System.Dynamic.Utils.DelegateHelpers.CreateObjectArrayDelegate(Type delegateType, Func2 handler) in System.Linq.Expressions.dll:token 0x600102d+0x2 at System.Linq.Expressions.Interpreter.LightLambda.MakeDelegate(Type delegateType) in System.Linq.Expressions.dll:token 0x6000c1c+0x31 at System.Linq.Expressions.Interpreter.LightDelegateCreator.CreateDelegate(IStrongBox[] closure) in System.Linq.Expressions.dll:token 0x6000c19+0x0 at System.Linq.Expressions.Interpreter.LightDelegateCreator.CreateDelegate() in System.Linq.Expressions.dll:token 0x6000c18+0x0 at System.Linq.Expressions.Expression1[[SpanJson.JsonSerializer.NonGeneric.Inner2.DeserializeDelegate[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver1[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].Compile() in System.Linq.Expressions.dll:token 0x6000641+0x3
at SpanJson.JsonSerializer.NonGeneric.Inner2[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver1[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].BuildDeserializer(Type type) in G:\MonoGroup\spanjson\SpanJson\JsonSerializer.NonGeneric.cs:line 233
at SpanJson.JsonSerializer.NonGeneric.Inner2[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver1[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].BuildInvoker(Type type) in G:\MonoGroup\spanjson\SpanJson\JsonSerializer.NonGeneric.cs:line 160
at SpanJson.JsonSerializer.NonGeneric.Inner2.<>c[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver1[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].b__2_0(Type x) in G:\MonoGroup\spanjson\SpanJson\JsonSerializer.NonGeneric.cs:line 44
at System.Collections.Concurrent.ConcurrentDictionary2[[System.Type, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.JsonSerializer.NonGeneric.Inner2.Invoker[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver1[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].GetOrAdd(Type key, Func2 valueFactory) in System.Collections.Concurrent.dll:token 0x60000d1+0x47
at SpanJson.JsonSerializer.NonGeneric.Inner2[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver1[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].InnerSerializeToString(Object input) in G:\MonoGroup\spanjson\SpanJson\JsonSerializer.NonGeneric.cs:line 44
at SpanJson.JsonSerializer.NonGeneric.Utf16.Serialize[ExcludeNullsOriginalCaseResolver`1](Object input) in G:\MonoGroup\spanjson\SpanJson\JsonSerializer.NonGeneric.cs:line 416
at SpanJson.JsonSerializer.NonGeneric.Utf16.Serialize(Object input) in G:\MonoGroup\spanjson\SpanJson\JsonSerializer.NonGeneric.cs:line 346
at UnrealEngine.Game.Tests.SpanJson.SpanJson.Run() in /Users/game-netease/unrealmono/UEDemo-427/UEDemo/Content/Script/Game/Tests/SpanJson/SpanJson.cs:line 27
···

Regression?

we have only try use on .net7, but I think .net8 also have this problem.

Known Workarounds

no

Configuration

ios

Other information

No response

Author: srxqds
Assignees: -
Labels:

untriaged, os-ios

Milestone: -

@ghost
Copy link

ghost commented Feb 22, 2024

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

Issue Details

Description

we are using Spanjson on ios use interp mode, it will throw exception when use expression generate deserialize/serialize code

Reproduction Steps

our source code:

internal class SpanJson
	{
		/// <summary>
		/// 一个简单的SpanJson测试用例
		/// </summary>
		[Test("SpanJson.SimpleSample")]
		public static void Run()
		{
			Person person = new Person { Name = "John Doe", Age = 30 };

			//Utf16
			{
				//Generic
				{
					var json = JsonSerializer.Generic.Utf16.Serialize(person);
					var deserializeData = JsonSerializer.Generic.Utf16.Deserialize<Person>(json);
					TestUtility.Check(deserializeData.Name == person.Name && deserializeData.Age == person.Age);
				}

				//NonGeneric
				{
					var json = JsonSerializer.NonGeneric.Utf16.Serialize(person);
					var deserializeData = JsonSerializer.NonGeneric.Utf16.Deserialize(json, typeof(Person)) as Person;
					TestUtility.Check(deserializeData.Name == person.Name && deserializeData.Age == person.Age);
				}
			}

			//Utf8
			{
				//Generic
				{
					var bytes = JsonSerializer.Generic.Utf8.Serialize(person);
					var deserializeData = JsonSerializer.Generic.Utf8.Deserialize<Person>(bytes);
					TestUtility.Check(deserializeData.Name == person.Name && deserializeData.Age == person.Age);
				}

				//NonGeneric
				{
					var bytes = JsonSerializer.NonGeneric.Utf8.Serialize(person);
					var deserializeData = JsonSerializer.NonGeneric.Utf8.Deserialize(bytes, typeof(Person)) as Person;
					TestUtility.Check(deserializeData.Name == person.Name && deserializeData.Age == person.Age);
				}
			}
		}
	}

	[JsonFormatterGenerator]
	public class Person
	{
		public string Name { get; set; }
		public int Age { get; set; }
	}

Expected behavior

walk correctly

Actual behavior

throw exception, the stacktrace show below:
···
Exception Test Name: SpanJson.SimpleSample
Cannot box IsByRefLike type 'System.ReadOnlySpan1' at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure, Boolean allowClosed) in System.Private.CoreLib.dll:token 0x6000258+0x86 at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method, Boolean throwOnBindFailure) in System.Private.CoreLib.dll:token 0x6000256+0x0 at System.Delegate.CreateDelegate(Type type, Object firstArgument, MethodInfo method) in System.Private.CoreLib.dll:token 0x600026d+0x0 at System.Reflection.Emit.DynamicMethod.CreateDelegate(Type delegateType, Object target) in System.Private.CoreLib.dll:token 0x6005d6b+0x11 at System.Dynamic.Utils.DelegateHelpers.CreateObjectArrayDelegateRefEmit(Type delegateType, Func2 handler) in System.Linq.Expressions.dll:token 0x6001038+0x355
at System.Dynamic.Utils.DelegateHelpers.CreateObjectArrayDelegate(Type delegateType, Func2 handler) in System.Linq.Expressions.dll:token 0x600102d+0x2 at System.Linq.Expressions.Interpreter.LightLambda.MakeDelegate(Type delegateType) in System.Linq.Expressions.dll:token 0x6000c1c+0x31 at System.Linq.Expressions.Interpreter.LightDelegateCreator.CreateDelegate(IStrongBox[] closure) in System.Linq.Expressions.dll:token 0x6000c19+0x0 at System.Linq.Expressions.Interpreter.LightDelegateCreator.CreateDelegate() in System.Linq.Expressions.dll:token 0x6000c18+0x0 at System.Linq.Expressions.Expression1[[SpanJson.JsonSerializer.NonGeneric.Inner2.DeserializeDelegate[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver1[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].Compile() in System.Linq.Expressions.dll:token 0x6000641+0x3
at SpanJson.JsonSerializer.NonGeneric.Inner2[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver1[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].BuildDeserializer(Type type) in G:\MonoGroup\spanjson\SpanJson\JsonSerializer.NonGeneric.cs:line 233
at SpanJson.JsonSerializer.NonGeneric.Inner2[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver1[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].BuildInvoker(Type type) in G:\MonoGroup\spanjson\SpanJson\JsonSerializer.NonGeneric.cs:line 160
at SpanJson.JsonSerializer.NonGeneric.Inner2.<>c[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver1[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].b__2_0(Type x) in G:\MonoGroup\spanjson\SpanJson\JsonSerializer.NonGeneric.cs:line 44
at System.Collections.Concurrent.ConcurrentDictionary2[[System.Type, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.JsonSerializer.NonGeneric.Inner2.Invoker[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver1[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].GetOrAdd(Type key, Func2 valueFactory) in System.Collections.Concurrent.dll:token 0x60000d1+0x47
at SpanJson.JsonSerializer.NonGeneric.Inner2[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver1[[System.Char, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].InnerSerializeToString(Object input) in G:\MonoGroup\spanjson\SpanJson\JsonSerializer.NonGeneric.cs:line 44
at SpanJson.JsonSerializer.NonGeneric.Utf16.Serialize[ExcludeNullsOriginalCaseResolver`1](Object input) in G:\MonoGroup\spanjson\SpanJson\JsonSerializer.NonGeneric.cs:line 416
at SpanJson.JsonSerializer.NonGeneric.Utf16.Serialize(Object input) in G:\MonoGroup\spanjson\SpanJson\JsonSerializer.NonGeneric.cs:line 346
at UnrealEngine.Game.Tests.SpanJson.SpanJson.Run() in /Users/game-netease/unrealmono/UEDemo-427/UEDemo/Content/Script/Game/Tests/SpanJson/SpanJson.cs:line 27
···

Regression?

we have only try use on .net7, but I think .net8 also have this problem.

Known Workarounds

no

Configuration

ios

Other information

No response

Author: srxqds
Assignees: -
Labels:

untriaged, area-Codegen-Interpreter-mono, os-ios

Milestone: -

@steveisok steveisok added this to the 9.0.0 milestone Feb 22, 2024
@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Feb 22, 2024
@steveisok
Copy link
Member

@srxqds I'd expect the type of exception you're getting to occur under full aot mode. Can you double check that you are indeed using the interpreter?

@srxqds
Copy link
Contributor Author

srxqds commented Feb 23, 2024

@srxqds I'd expect the type of exception you're getting to occur under full aot mode. Can you double check that you are indeed using the interpreter?

yes, we use interpreter mode

@srxqds
Copy link
Contributor Author

srxqds commented Feb 26, 2024

@steveisok @BrzVlad could you take time to fix it?

@BrzVlad
Copy link
Member

BrzVlad commented Feb 26, 2024

What is Spanjson ? Boxing a byref type doesn't make sense to me.

@srxqds
Copy link
Contributor Author

srxqds commented Feb 26, 2024

What is Spanjson ? Boxing a byref type doesn't make sense to me.

the source code you can find here: https://github.com/Tornhoof/SpanJson/blob/3849bc28847e2e3ec6d2474283f512a3315b42ae/SpanJson/JsonSerializer.NonGeneric.cs#L213-L226

it can work on mono execute with jit and coreclr

@srxqds
Copy link
Contributor Author

srxqds commented Feb 27, 2024

anyone can help to solve this problem?

@BrzVlad
Copy link
Member

BrzVlad commented Feb 27, 2024

can you provide a full desktop console project that should fail with interpreter ?

@srxqds
Copy link
Contributor Author

srxqds commented Feb 28, 2024

can you provide a full desktop console project that should fail with interpreter ?
SpanJsonTest.zip

@BrzVlad
Copy link
Member

BrzVlad commented Feb 28, 2024

I'm actually not able to reproduce it on this sample with desktop interpreter. I haven't yet tried to port the code to an ios project.

@srxqds
Copy link
Contributor Author

srxqds commented Mar 4, 2024

we are using embed mono in ue, the project is too big to share with you. anyone can help me port the c ode to ios project?

@AlexeiNaabal
Copy link

AlexeiNaabal commented Mar 20, 2024

I'm actually not able to reproduce it on this sample with desktop interpreter. I haven't yet tried to port the code to an ios project.

We've tested this repro on ios device and reproduced this error, based on the iOS sample on the repo and the SpanJsonTest
The config we use are:

  • branch release/7.0
  • iOS sample project on the repo, plus the code on the SpanJsonTest
  • enable Interp when building the iOS sample project and the later AOT compiling
  • toggle off PublishTrimmed

The final ios sample's Makefile (where modified)

MONO_CONFIG?=Debug
MONO_ARCH?=arm64 # since we building on Apple Silicon PC, we changed this to arm64
DOTNET := ../../../../dotnet.sh
...
run: clean appbuilder
	$(DOTNET) publish \
	-c $(MONO_CONFIG) \
	/p:TargetOS=iOS \
	/p:TargetArchitecture=$(MONO_ARCH) \
	/p:UseLLVM=$(USE_LLVM) \
	/p:ForceAOT=$(AOT) \
	/p:MonoForceInterpreter=true \
	'/p:RuntimeComponents="$(RUNTIME_COMPONENTS)"' \
	'/p:DeployAndRun="$(DEPLOY_AND_RUN)"' \
	'/p:DiagnosticPorts="$(DIAGNOSTIC_PORTS)"'

The final ios sample's Program.csproj (where modified)

...
  <PropertyGroup>
    <PublishTrimmed>false</PublishTrimmed>
    <TrimMode>Link</TrimMode>
  </PropertyGroup>
...
  <PropertyGroup>
    <AOTMode Condition="'$(TargetOS)' != 'MacCatalyst'">Full</AOTMode>
    <AOTMode Condition="'$(TargetOS)' == 'MacCatalyst' and '$(MonoForceInterpreter)' != 'true'">Full</AOTMode>
    <AOTMode Condition="'$(TargetOS)' == 'MacCatalyst' and '$(MonoForceInterpreter)' == 'true'">JustInterp</AOTMode>
    <AOTMode Condition="'$(TargetOS)' == 'iOS' and '$(MonoForceInterpreter)' == 'true'">JustInterp</AOTMode>
  </PropertyGroup>

The final ios sample's Program.cs:

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using SpanJson;

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public static class Program
{
    // Defined in main.m
    [DllImport("__Internal")]
    private static extern void ios_set_text(string value);

    [DllImport("__Internal")]
    unsafe private static extern void ios_register_button_click(delegate* unmanaged<void> callback);

    private static int counter = 0;

    // Called by native code, see main.m
    [UnmanagedCallersOnly]
    private static void OnButtonClick()
    {
        ios_set_text("OnButtonClick! #" + counter++);
    }

#if CI_TEST
    public static async Task<int> Main(string[] args)
#else
    public static async Task Main(string[] args)
#endif
    {
        Person person = new Person { Name = "John Doe", Age = 30 };

        //Utf16
        var json = JsonSerializer.NonGeneric.Utf16.Serialize(person);
        var deserializeData = JsonSerializer.NonGeneric.Utf16.Deserialize(json, typeof(Person)) as Person;
        
        unsafe {
            // Register a managed callback (will be called by UIButton, see main.m)
            delegate* unmanaged<void> unmanagedPtr = &OnButtonClick;
            ios_register_button_click(unmanagedPtr);
        }
        const string msg = "Hello World!\n.NET 5.0";
        for (int i = 0; i < msg.Length; i++)
        {
            // a kind of an animation
            ios_set_text(msg.Substring(0, i + 1));
            await Task.Delay(100);
        }

        Console.WriteLine("Done!");
#if CI_TEST
        await Task.Delay(5000);
        return 42;
#else
        await Task.Delay(-1);
#endif 
    }
}

We first build the mono runtime on our Apple Silicon PC with ./build.sh -arch arm64 -os ios -s mono+libs, then modified the files as mentioned above, finally use make run under the iOS sample folder to generate the project files.
might need further investigation?

@AlexeiNaabal
Copy link

AlexeiNaabal commented Mar 25, 2024

We also tested this repro with release/8.0 on iOS device, the runtime did throw exception, though the message is different, but with further check, we believe this exception behavior is consistent with the release/7.0

We added the /p:MonoForceInterpreter=true \ to the Makefile's run: clean appbuilder block, and disable the <PublishTrimmed> property, and add the PackageReference of SpanJson by using command line dotnet add pakcage SpanJson on the csproj file of the HelloiOS project. The c# code is same as we provided above that with release/7.0.

The runtime exception is like:

2024-03-25 09:25:43.736931+0800 HelloiOS[52931:2050639] Unhandled managed exceptions:
The type initializer for 'Inner`3' threw an exception. (System.TypeInitializationException)
   at System.Object.lambda_method1(Closure , Object )
   at SpanJson.JsonSerializer.NonGeneric.Inner`2[[System.Char, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver`1[[System.Char, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].InnerSerializeToString(Object )
   at SpanJson.JsonSerializer.NonGeneric.Utf16.Serialize[ExcludeNullsOriginalCaseResolver`1](Object )
   at SpanJson.JsonSerializer.NonGeneric.Utf16.Serialize(Object )
   at Program.Main(String[] ) in /Users/{wut}/runtime/src/mono/sample/iOS/Program.cs:line 58
   at Program.<Main>(String[] )

@srxqds
Copy link
Contributor Author

srxqds commented Mar 25, 2024

@BrzVlad can you take time to look up this problem for .net8.0 ?

@srxqds
Copy link
Contributor Author

srxqds commented Mar 26, 2024

we have

We also tested this repro with release/8.0 on iOS device, the runtime did throw exception, though the message is different, but with further check, we believe this exception behavior is consistent with the release/7.0

We added the /p:MonoForceInterpreter=true \ to the Makefile's run: clean appbuilder block, and disable the <PublishTrimmed> property, and add the PackageReference of SpanJson by using command line dotnet add pakcage SpanJson on the csproj file of the HelloiOS project. The c# code is same as we provided above that with release/7.0.

The runtime exception is like:

2024-03-25 09:25:43.736931+0800 HelloiOS[52931:2050639] Unhandled managed exceptions:
The type initializer for 'Inner`3' threw an exception. (System.TypeInitializationException)
   at System.Object.lambda_method1(Closure , Object )
   at SpanJson.JsonSerializer.NonGeneric.Inner`2[[System.Char, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver`1[[System.Char, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].InnerSerializeToString(Object )
   at SpanJson.JsonSerializer.NonGeneric.Utf16.Serialize[ExcludeNullsOriginalCaseResolver`1](Object )
   at SpanJson.JsonSerializer.NonGeneric.Utf16.Serialize(Object )
   at Program.Main(String[] ) in /Users/{wut}/runtime/src/mono/sample/iOS/Program.cs:line 58
   at Program.<Main>(String[] )

hi, @steveisok @BrzVlad you can reproduce by this step

@Liangjia0411
Copy link

"In the v8.0.3 tag, setting the <PublishTrimmed> property to true in the csproj file results in the same error. However, changing this property to false resolves the issue and the error no longer occurs."

I hope this helps! If you have any more requests or questions, feel free to ask.

We also tested this repro with release/8.0 on iOS device, the runtime did throw exception, though the message is different, but with further check, we believe this exception behavior is consistent with the release/7.0

We added the /p:MonoForceInterpreter=true \ to the Makefile's run: clean appbuilder block, and disable the <PublishTrimmed> property, and add the PackageReference of SpanJson by using command line dotnet add pakcage SpanJson on the csproj file of the HelloiOS project. The c# code is same as we provided above that with release/7.0.

The runtime exception is like:

2024-03-25 09:25:43.736931+0800 HelloiOS[52931:2050639] Unhandled managed exceptions:
The type initializer for 'Inner`3' threw an exception. (System.TypeInitializationException)
   at System.Object.lambda_method1(Closure , Object )
   at SpanJson.JsonSerializer.NonGeneric.Inner`2[[System.Char, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[SpanJson.Resolvers.ExcludeNullsOriginalCaseResolver`1[[System.Char, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]], SpanJson, Version=4.0.1.0, Culture=neutral, PublicKeyToken=12740fa6726bc6d3]].InnerSerializeToString(Object )
   at SpanJson.JsonSerializer.NonGeneric.Utf16.Serialize[ExcludeNullsOriginalCaseResolver`1](Object )
   at SpanJson.JsonSerializer.NonGeneric.Utf16.Serialize(Object )
   at Program.Main(String[] ) in /Users/{wut}/runtime/src/mono/sample/iOS/Program.cs:line 58
   at Program.<Main>(String[] )

@vitek-karas vitek-karas modified the milestones: 9.0.0, 10.0.0 Sep 10, 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

8 participants
@steveisok @BrzVlad @srxqds @jeffschwMSFT @vitek-karas @AlexeiNaabal @Liangjia0411 and others