From 5d8e0e61ad9330caa05e30c282e84a8afa9f9bda Mon Sep 17 00:00:00 2001 From: neuecc Date: Wed, 10 Jun 2020 11:36:58 +0900 Subject: [PATCH] workaround for IL2CPP bug, back to zero allocation --- .../AsyncUniTaskVoidMethodBuilder.cs | 10 ++++ .../CompilerServices/StateMachineRunner.cs | 60 +++++++++++++++---- 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs index 754dde6..82e91f3 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/AsyncUniTaskVoidMethodBuilder.cs @@ -41,7 +41,12 @@ namespace Cysharp.Threading.Tasks.CompilerServices // runner is finished, return first. if (runner != null) { +#if ENABLE_IL2CPP + // workaround for IL2CPP bug. + PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, runner.ReturnAction); +#else runner.Return(); +#endif runner = null; } @@ -56,7 +61,12 @@ namespace Cysharp.Threading.Tasks.CompilerServices // runner is finished, return. if (runner != null) { +#if ENABLE_IL2CPP + // workaround for IL2CPP bug. + PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, runner.ReturnAction); +#else runner.Return(); +#endif runner = null; } } diff --git a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/StateMachineRunner.cs b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/StateMachineRunner.cs index 067c048..d7d59dd 100644 --- a/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/StateMachineRunner.cs +++ b/src/UniTask/Assets/Plugins/UniTask/Runtime/CompilerServices/StateMachineRunner.cs @@ -12,6 +12,10 @@ namespace Cysharp.Threading.Tasks.CompilerServices { Action MoveNext { get; } void Return(); + +#if ENABLE_IL2CPP + Action ReturnAction { get; } +#endif } internal interface IStateMachineRunnerPromise : IUniTaskSource @@ -32,6 +36,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices internal static class StateMachineUtility { + // Get AsyncStateMachine internal state to check IL2CPP bug public static int GetState(IAsyncStateMachine stateMachine) { var info = stateMachine.GetType().GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) @@ -46,16 +51,19 @@ namespace Cysharp.Threading.Tasks.CompilerServices static TaskPool> pool; #if ENABLE_IL2CPP - IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue. -#else - TStateMachine stateMachine; + public Action ReturnAction { get; } #endif + TStateMachine stateMachine; + public Action MoveNext { get; } public AsyncUniTaskVoid() { MoveNext = Run; +#if ENABLE_IL2CPP + ReturnAction = Return; +#endif } public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunner runnerFieldRef) @@ -118,18 +126,19 @@ namespace Cysharp.Threading.Tasks.CompilerServices static TaskPool> pool; #if ENABLE_IL2CPP - IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue. -#else - TStateMachine stateMachine; + readonly Action returnDelegate; #endif - public Action MoveNext { get; } + TStateMachine stateMachine; UniTaskCompletionSourceCore core; AsyncUniTask() { MoveNext = Run; +#if ENABLE_IL2CPP + returnDelegate = Return; +#endif } public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise runnerPromiseFieldRef) @@ -151,6 +160,14 @@ namespace Cysharp.Threading.Tasks.CompilerServices TaskPool.RegisterSizeGetter(typeof(AsyncUniTask), () => pool.Size); } + void Return() + { + TaskTracker.RemoveTracking(this); + core.Reset(); + stateMachine = default; + pool.TryPush(this); + } + bool TryReturn() { TaskTracker.RemoveTracking(this); @@ -196,7 +213,12 @@ namespace Cysharp.Threading.Tasks.CompilerServices } finally { +#if ENABLE_IL2CPP + // workaround for IL2CPP bug. + PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, returnDelegate); +#else TryReturn(); +#endif } } @@ -233,18 +255,20 @@ namespace Cysharp.Threading.Tasks.CompilerServices static TaskPool> pool; #if ENABLE_IL2CPP - IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue. -#else - TStateMachine stateMachine; + readonly Action returnDelegate; #endif public Action MoveNext { get; } + TStateMachine stateMachine; UniTaskCompletionSourceCore core; AsyncUniTask() { MoveNext = Run; +#if ENABLE_IL2CPP + returnDelegate = Return; +#endif } public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise runnerPromiseFieldRef) @@ -257,11 +281,8 @@ namespace Cysharp.Threading.Tasks.CompilerServices runnerPromiseFieldRef = result; // set runner before copied. result.stateMachine = stateMachine; // copy struct StateMachine(in release build). - - // UnityEngine.Debug.Log($"SetStateMachine State:" + StateMachineUtility.GetState(stateMachine)); } - public AsyncUniTask NextNode { get; set; } static AsyncUniTask() @@ -269,6 +290,14 @@ namespace Cysharp.Threading.Tasks.CompilerServices TaskPool.RegisterSizeGetter(typeof(AsyncUniTask), () => pool.Size); } + void Return() + { + TaskTracker.RemoveTracking(this); + core.Reset(); + stateMachine = default; + pool.TryPush(this); + } + bool TryReturn() { TaskTracker.RemoveTracking(this); @@ -315,7 +344,12 @@ namespace Cysharp.Threading.Tasks.CompilerServices } finally { +#if ENABLE_IL2CPP + // workaround for IL2CPP bug. + PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, returnDelegate); +#else TryReturn(); +#endif } }