workaround for IL2CPP bug, back to zero allocation

master
neuecc 2020-06-10 11:36:58 +09:00
parent 478126e256
commit 5d8e0e61ad
2 changed files with 57 additions and 13 deletions

View File

@ -41,7 +41,12 @@ namespace Cysharp.Threading.Tasks.CompilerServices
// runner is finished, return first. // runner is finished, return first.
if (runner != null) if (runner != null)
{ {
#if ENABLE_IL2CPP
// workaround for IL2CPP bug.
PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, runner.ReturnAction);
#else
runner.Return(); runner.Return();
#endif
runner = null; runner = null;
} }
@ -56,7 +61,12 @@ namespace Cysharp.Threading.Tasks.CompilerServices
// runner is finished, return. // runner is finished, return.
if (runner != null) if (runner != null)
{ {
#if ENABLE_IL2CPP
// workaround for IL2CPP bug.
PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, runner.ReturnAction);
#else
runner.Return(); runner.Return();
#endif
runner = null; runner = null;
} }
} }

View File

@ -12,6 +12,10 @@ namespace Cysharp.Threading.Tasks.CompilerServices
{ {
Action MoveNext { get; } Action MoveNext { get; }
void Return(); void Return();
#if ENABLE_IL2CPP
Action ReturnAction { get; }
#endif
} }
internal interface IStateMachineRunnerPromise : IUniTaskSource internal interface IStateMachineRunnerPromise : IUniTaskSource
@ -32,6 +36,7 @@ namespace Cysharp.Threading.Tasks.CompilerServices
internal static class StateMachineUtility internal static class StateMachineUtility
{ {
// Get AsyncStateMachine internal state to check IL2CPP bug
public static int GetState(IAsyncStateMachine stateMachine) public static int GetState(IAsyncStateMachine stateMachine)
{ {
var info = stateMachine.GetType().GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) 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<AsyncUniTaskVoid<TStateMachine>> pool; static TaskPool<AsyncUniTaskVoid<TStateMachine>> pool;
#if ENABLE_IL2CPP #if ENABLE_IL2CPP
IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue. public Action ReturnAction { get; }
#else
TStateMachine stateMachine;
#endif #endif
TStateMachine stateMachine;
public Action MoveNext { get; } public Action MoveNext { get; }
public AsyncUniTaskVoid() public AsyncUniTaskVoid()
{ {
MoveNext = Run; MoveNext = Run;
#if ENABLE_IL2CPP
ReturnAction = Return;
#endif
} }
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunner runnerFieldRef) public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunner runnerFieldRef)
@ -118,18 +126,19 @@ namespace Cysharp.Threading.Tasks.CompilerServices
static TaskPool<AsyncUniTask<TStateMachine>> pool; static TaskPool<AsyncUniTask<TStateMachine>> pool;
#if ENABLE_IL2CPP #if ENABLE_IL2CPP
IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue. readonly Action returnDelegate;
#else
TStateMachine stateMachine;
#endif #endif
public Action MoveNext { get; } public Action MoveNext { get; }
TStateMachine stateMachine;
UniTaskCompletionSourceCore<AsyncUnit> core; UniTaskCompletionSourceCore<AsyncUnit> core;
AsyncUniTask() AsyncUniTask()
{ {
MoveNext = Run; MoveNext = Run;
#if ENABLE_IL2CPP
returnDelegate = Return;
#endif
} }
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise runnerPromiseFieldRef) public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise runnerPromiseFieldRef)
@ -151,6 +160,14 @@ namespace Cysharp.Threading.Tasks.CompilerServices
TaskPool.RegisterSizeGetter(typeof(AsyncUniTask<TStateMachine>), () => pool.Size); TaskPool.RegisterSizeGetter(typeof(AsyncUniTask<TStateMachine>), () => pool.Size);
} }
void Return()
{
TaskTracker.RemoveTracking(this);
core.Reset();
stateMachine = default;
pool.TryPush(this);
}
bool TryReturn() bool TryReturn()
{ {
TaskTracker.RemoveTracking(this); TaskTracker.RemoveTracking(this);
@ -196,7 +213,12 @@ namespace Cysharp.Threading.Tasks.CompilerServices
} }
finally finally
{ {
#if ENABLE_IL2CPP
// workaround for IL2CPP bug.
PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, returnDelegate);
#else
TryReturn(); TryReturn();
#endif
} }
} }
@ -233,18 +255,20 @@ namespace Cysharp.Threading.Tasks.CompilerServices
static TaskPool<AsyncUniTask<TStateMachine, T>> pool; static TaskPool<AsyncUniTask<TStateMachine, T>> pool;
#if ENABLE_IL2CPP #if ENABLE_IL2CPP
IAsyncStateMachine stateMachine; // unfortunatelly boxed to fix IL2CPP issue. readonly Action returnDelegate;
#else
TStateMachine stateMachine;
#endif #endif
public Action MoveNext { get; } public Action MoveNext { get; }
TStateMachine stateMachine;
UniTaskCompletionSourceCore<T> core; UniTaskCompletionSourceCore<T> core;
AsyncUniTask() AsyncUniTask()
{ {
MoveNext = Run; MoveNext = Run;
#if ENABLE_IL2CPP
returnDelegate = Return;
#endif
} }
public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise<T> runnerPromiseFieldRef) public static void SetStateMachine(ref TStateMachine stateMachine, ref IStateMachineRunnerPromise<T> runnerPromiseFieldRef)
@ -257,11 +281,8 @@ namespace Cysharp.Threading.Tasks.CompilerServices
runnerPromiseFieldRef = result; // set runner before copied. runnerPromiseFieldRef = result; // set runner before copied.
result.stateMachine = stateMachine; // copy struct StateMachine(in release build). result.stateMachine = stateMachine; // copy struct StateMachine(in release build).
// UnityEngine.Debug.Log($"SetStateMachine State:" + StateMachineUtility.GetState(stateMachine));
} }
public AsyncUniTask<TStateMachine, T> NextNode { get; set; } public AsyncUniTask<TStateMachine, T> NextNode { get; set; }
static AsyncUniTask() static AsyncUniTask()
@ -269,6 +290,14 @@ namespace Cysharp.Threading.Tasks.CompilerServices
TaskPool.RegisterSizeGetter(typeof(AsyncUniTask<TStateMachine, T>), () => pool.Size); TaskPool.RegisterSizeGetter(typeof(AsyncUniTask<TStateMachine, T>), () => pool.Size);
} }
void Return()
{
TaskTracker.RemoveTracking(this);
core.Reset();
stateMachine = default;
pool.TryPush(this);
}
bool TryReturn() bool TryReturn()
{ {
TaskTracker.RemoveTracking(this); TaskTracker.RemoveTracking(this);
@ -315,7 +344,12 @@ namespace Cysharp.Threading.Tasks.CompilerServices
} }
finally finally
{ {
#if ENABLE_IL2CPP
// workaround for IL2CPP bug.
PlayerLoopHelper.AddContinuation(PlayerLoopTiming.LastPostLateUpdate, returnDelegate);
#else
TryReturn(); TryReturn();
#endif
} }
} }