unity3d关于IOS的AOT编译注意事项 ( AOT Exception Patterns and Hacks )
2015-12-04 15:56
531 查看
Runnning on iOS sometimes raise runtime exception.
Generics is easy to cause a problem of AOT. UniRx use generics pipeline heavyly. But we cannnot be afraid if we know a pattern and counterplan. If you can't avoid AOT problem, please report to GitHub issues.
We can't use Interlocked.ComapreExchange[T]. (wrapper native-to-managed) exception needs MonoPInvokeCallback(see:Unity TroubleShooting), but Interlocked.CompareExchange[T]
is internal, it's in mscorlib.dll. Alterenate, we can use Interlocked.CompareExchange(object).
We can avoid by compiler hint.
We can avoid by capture external value.
This technique is very useful for use UniRx because Rx(LINQ) use lambda heavily.
We can avoid UniRx's Utility - AsSafeEnumerable.
https://github.com/mono/mono/commit/071f495d6a4ce4951e2b2c9069586bd5bcde5fbb ). But Unity's mono runtime is 2.6. I post upgrade Enumerable.cs request on Unity Feedback.
Upgrade Enumerable.cs for avoid AOT Problem of LINQ(Average etc...) .I'm glad to if you vote.
System.ExecutionEngineException: Attempting to JIT compile method
Generics is easy to cause a problem of AOT. UniRx use generics pipeline heavyly. But we cannnot be afraid if we know a pattern and counterplan. If you can't avoid AOT problem, please report to GitHub issues.
Interlocked.CompareExchange
// ExecutionEngineException: Attempting to JIT compile method '(wrapper native-to-managed)' while running with --aot-only var a = "hoge"; Interlocked.CompareExchange<string>(ref a, "hugahuga", "hoge"); // It's Ok! CompareExchange(int, object, etc...) works. object b = "hoge"; Interlocked.CompareExchange(ref b, "hugahuga", "hoge");
We can't use Interlocked.ComapreExchange[T]. (wrapper native-to-managed) exception needs MonoPInvokeCallback(see:Unity TroubleShooting), but Interlocked.CompareExchange[T]
is internal, it's in mscorlib.dll. Alterenate, we can use Interlocked.CompareExchange(object).
Interface + GenericsMethod + Struct
The Three pair kills application.public interface IMyInterface { void MyMethod<T>(T x); } public class MyImpl : IMyInterface { public void MyMethod<T>(T x) { } } IMyInterface intf = new MyImpl(); intf.MyMethod("hogehoge"); // ReferenceType is not dead // System.ExecutionEngineException: Attempting to JIT compile method 'MyImpl:MyMethod<int> (int)' while running with --aot-only. intf.MyMethod(100); // die
We can avoid by compiler hint.
// don't need call, write specified type anywhere. static void _CompilerHint() { new MyImpl().MyMethod(default(int)); } void Awake() { IMyInterface intf = new MyImpl(); intf.MyMethod(100); // Struct but not dead }
Lambda + Generics + Struct
static void Death<T>() { var act = new Action<T>(_ => { Debug.Log("hoge"); }); // not dead yet // System.ExecutionEngineException: Attempting to JIT compile method '<Death>b__0<int> (int)' while running with --aot-only. act(default(T)); // die } // call with struct cause exception(If class run perfectly) Death<int>();
We can avoid by capture external value.
static void Death<T>() { var _dummy = 0; var act = new Action<T>(_ => { Debug.Log("hoge"); _dummy.GetHashCode(); // capture external variable }); act(default(T)); // not dead } Death<int>();
This technique is very useful for use UniRx because Rx(LINQ) use lambda heavily.
GenericsMethod + Struct + Class
This is complex and seriously problem.public static void Run() { // call by reference type cause exception // System.ExecutionEngineException: Attempting to JIT compile method 'Method2<int, object> ()' while running with --aot-only. Method1<object>(); } public static void Method1<T1>() { Method2<int, T1>(); // one side as value type } // Two type args and has return type static string Method2<T1, T2>() { return ""; }
Enum Array(List)
Enum is sometimes dangerous.public enum MyEnum { Apple } // System.ExecutionEngineException: Attempting to JIT compile method '(wrapper managed-to-managed) MyEnum[]:System.Collections.Generic.ICollection`1.CopyTo (UniRx.MyEnum[],int)' while running with --aot-only. new[] { MyEnum.Apple }.ToArray();
We can avoid UniRx's Utility - AsSafeEnumerable.
new[] { MyEnum.Apple }.AsSafeEnumerable().ToArray();
AotSafe Utilities
Struct often cause storange behaviour. You can wrap IEnumerable/IObservable's element to Tuple1(as class wrapper).Enumerable.Range(1, 10).WrapValueToClass(); // IEnumerable<Tuple<int>> Observable.Range(1, 10).WrapValueToClass(); // IObservable<Tuple<int>>
LINQ and AOT
Some LINQ methods can't work on iOS. It's not LINQ limitation because mono 2.8 already fixed(such as this patchhttps://github.com/mono/mono/commit/071f495d6a4ce4951e2b2c9069586bd5bcde5fbb ). But Unity's mono runtime is 2.6. I post upgrade Enumerable.cs request on Unity Feedback.
Upgrade Enumerable.cs for avoid AOT Problem of LINQ(Average etc...) .I'm glad to if you vote.
相关文章推荐
- 联机Unity Profile技巧
- 总结使用Unity 3D优化游戏运行性能的经验
- unity NGUI Tutorial Tools
- unity NGUI tutorial scroll view
- unity NGUI tutorial layout system
- Unity3D中的预制件(Prefab)的创建和使用说明!!!
- Unity中的自定义鼠标
- unity NGUI tutorial more events
- Unity android客户端实现双击跳过动画播放
- Unity中运用UDP广播服务器IP实现局域网联机
- unity NGUI Tutorial event system
- unity NGUI Tutorial context menus
- unity NUGUI tutorial the basics
- unity3D学习
- unity3d 随机物体生成器 工具
- 关于A*算法的研究
- unity与Android的交互
- 【Unity开发】简单的对象池实现
- Unity3d+ShareSDK+IOS9.1 编译错误(备忘)
- Unity局部高效实时阴影的思考和实现