Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
b7bb968
Set target method desc for resumption stubs
jakobbotsch Oct 1, 2025
d5d0864
Add JIT-EE boilerplate
jakobbotsch Oct 1, 2025
d7277fb
Add debug information for runtime async information
jakobbotsch Oct 1, 2025
6addd0e
Update managed view
jakobbotsch Oct 1, 2025
6a5bf19
Remove TODOs
jakobbotsch Oct 1, 2025
262260a
Leaf transition
jakobbotsch Oct 1, 2025
4e2a829
Comment
jakobbotsch Oct 1, 2025
820afa9
Delete unused enum
jakobbotsch Oct 1, 2025
3621eae
Restore comment
jakobbotsch Oct 1, 2025
f597424
Fix osx build
jakobbotsch Oct 1, 2025
6bb6cee
Fix GCC build
jakobbotsch Oct 1, 2025
f580e3f
Change sentinel value, fix contract
jakobbotsch Oct 2, 2025
55b9522
Bump R2R
jakobbotsch Oct 2, 2025
c9c64be
Clean up
jakobbotsch Oct 2, 2025
db77446
Expose async debug info accessor APIs
jakobbotsch Oct 2, 2025
c808390
Missed bumping R2R version for naot
jakobbotsch Oct 2, 2025
3ec5160
Fix reverse mapping to IL local nums
jakobbotsch Oct 2, 2025
bb12c77
Fix monotonicity for async vars
jakobbotsch Oct 2, 2025
bf3364b
Code style
jakobbotsch Oct 2, 2025
b49f38f
Fix JIT-EE prompt tools from Egor's instructions, allow use of experi…
jakobbotsch Oct 2, 2025
d1bf49f
Address feedback, make comment less misleading
jakobbotsch Oct 3, 2025
579714e
Add AsyncContinuationVarInfo.GCIndex
jakobbotsch Oct 6, 2025
c056793
Publish NextContinuation in TLS
jakobbotsch Oct 8, 2025
9679f91
Rename ThunkTask -> RuntimeAsyncTask
jakobbotsch Oct 8, 2025
7a34475
Merge branch 'main' of github.com:dotnet/runtime into jit-async-diagn…
jakobbotsch Oct 9, 2025
e839409
Report native offsets instead
jakobbotsch Oct 9, 2025
d8ad0c1
Run jit-format
jakobbotsch Oct 9, 2025
9fdd8a7
Print reported async debug info, always report it
jakobbotsch Oct 9, 2025
69e02db
Store target IPs in AsyncResumeILStubResolver
jakobbotsch Oct 14, 2025
68c245b
Fix bug
jakobbotsch Oct 14, 2025
2031f08
Remove BBF_INTERNAL from rethrow BB to avoid broken mappings
jakobbotsch Oct 15, 2025
b7576b2
Trampolines for resumption
jakobbotsch Oct 17, 2025
03f85ec
Merge branch 'main' of github.com:dotnet/runtime into jit-async-diagn…
jakobbotsch Oct 17, 2025
06fea81
Fix after merge
jakobbotsch Oct 17, 2025
29d8998
Enable runtime async testing
jakobbotsch Oct 17, 2025
cb7a943
Undo changes
jakobbotsch Oct 17, 2025
879ec4f
Hacky late Friday GC issue fix
jakobbotsch Oct 17, 2025
0749688
Fix 32 bit build
jakobbotsch Oct 17, 2025
6bcc004
Last block no longer always results in the last IG
jakobbotsch Oct 18, 2025
286baf9
Merge branch 'main' of github.com:dotnet/runtime into jit-async-diagn…
jakobbotsch Oct 18, 2025
8cf3a72
Fix after merge
jakobbotsch Oct 18, 2025
3096aa8
Run jit-format
jakobbotsch Oct 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,8 @@ private interface IRuntimeAsyncTaskOps<T>
static abstract ref byte GetResultStorage(T task);
}

/// <summary>
/// Represents a wrapped runtime async operation.
/// </summary>
// Represents execution of a chain of suspended and resuming runtime
// async functions.
private sealed class RuntimeAsyncTask<T> : Task<T>, ITaskCompletionAction
{
public RuntimeAsyncTask()
Expand Down Expand Up @@ -261,9 +260,8 @@ public static void PostToSyncContext(RuntimeAsyncTask<T> task, SynchronizationCo
}
}

/// <summary>
/// Represents a wrapped runtime async operation.
/// </summary>
// Represents execution of a chain of suspended and resuming runtime
// async functions.
private sealed class RuntimeAsyncTask : Task, ITaskCompletionAction
{
public RuntimeAsyncTask()
Expand Down Expand Up @@ -329,35 +327,55 @@ public static void PostToSyncContext(RuntimeAsyncTask task, SynchronizationConte

private static class RuntimeAsyncTaskCore
{
private unsafe struct NextContinuationData
{
public NextContinuationData* Next;
public Continuation* NextContinuation;
}

// To be used for async stack walking
[ThreadStatic]
private static unsafe NextContinuationData* t_nextContinuation;

public static unsafe void DispatchContinuations<T, TOps>(T task) where T : Task, ITaskCompletionAction where TOps : IRuntimeAsyncTaskOps<T>
{
ExecutionAndSyncBlockStore contexts = default;
contexts.Push();
Continuation? continuation = TOps.GetContinuationState(task);

ref NextContinuationData* nextContRef = ref t_nextContinuation;
NextContinuationData nextContinuationData;
nextContinuationData.Next = nextContRef;
nextContinuationData.NextContinuation = &continuation;

nextContRef = &nextContinuationData;

while (true)
{
Debug.Assert(continuation != null);
try
{
ref byte resultLoc = ref continuation.Next != null ? ref continuation.Next.GetResultStorageOrNull() : ref TOps.GetResultStorage(task);
Continuation? newContinuation = continuation.Resume(continuation, ref resultLoc);
Continuation? curContinuation = continuation;
Debug.Assert(curContinuation != null);
Continuation? nextContinuation = curContinuation.Next;
continuation = nextContinuation;

ref byte resultLoc = ref nextContinuation != null ? ref nextContinuation.GetResultStorageOrNull() : ref TOps.GetResultStorage(task);
Continuation? newContinuation = curContinuation.Resume(curContinuation, ref resultLoc);

if (newContinuation != null)
{
newContinuation.Next = continuation.Next;
newContinuation.Next = nextContinuation;
HandleSuspended<T, TOps>(task);
contexts.Pop();
t_nextContinuation = nextContinuationData.Next;
return;
}

continuation = continuation.Next;
}
catch (Exception ex)
{
Debug.Assert(continuation != null);
Continuation? nextContinuation = UnwindToPossibleHandler(continuation);
if (nextContinuation == null)
Continuation? handlerContinuation = UnwindToPossibleHandler(continuation);
if (handlerContinuation == null)
{
// Tail of AsyncTaskMethodBuilderT.SetException
bool successfullySet = ex is OperationCanceledException oce ?
Expand All @@ -366,6 +384,8 @@ public static unsafe void DispatchContinuations<T, TOps>(T task) where T : Task,

contexts.Pop();

t_nextContinuation = nextContinuationData.Next;

if (!successfullySet)
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.TaskT_TransitionToFinal_AlreadyCompleted);
Expand All @@ -374,9 +394,8 @@ public static unsafe void DispatchContinuations<T, TOps>(T task) where T : Task,
return;
}

nextContinuation.SetException(ex);

continuation = nextContinuation;
handlerContinuation.SetException(ex);
continuation = handlerContinuation;
}

if (continuation == null)
Expand All @@ -385,6 +404,8 @@ public static unsafe void DispatchContinuations<T, TOps>(T task) where T : Task,

contexts.Pop();

t_nextContinuation = nextContinuationData.Next;

if (!successfullySet)
{
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.TaskT_TransitionToFinal_AlreadyCompleted);
Expand All @@ -396,23 +417,20 @@ public static unsafe void DispatchContinuations<T, TOps>(T task) where T : Task,
if (QueueContinuationFollowUpActionIfNecessary<T, TOps>(task, continuation))
{
contexts.Pop();
t_nextContinuation = nextContinuationData.Next;
return;
}
}
}

private static Continuation? UnwindToPossibleHandler(Continuation continuation)
private static Continuation? UnwindToPossibleHandler(Continuation? continuation)
{
while (true)
{
Continuation? nextContinuation = continuation.Next;
if (nextContinuation == null)
return null;

if ((nextContinuation.Flags & ContinuationFlags.HasException) != 0)
return nextContinuation;
if (continuation == null || (continuation.Flags & ContinuationFlags.HasException) != 0)
return continuation;

continuation = nextContinuation;
continuation = continuation.Next;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/inc/clrconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -715,7 +715,7 @@ RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableRiscV64Zbb, W("EnableRiscV64
#endif

// Runtime-async
RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_RuntimeAsync, W("RuntimeAsync"), 0, "Enables runtime async method support")
RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_RuntimeAsync, W("RuntimeAsync"), 1, "Enables runtime async method support")

///
/// Uncategorized
Expand Down
25 changes: 25 additions & 0 deletions src/coreclr/inc/cordebuginfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -431,4 +431,29 @@ class ICorDebugInfo
// Source information about the IL instruction in the inlinee
SourceTypes Source;
};

struct AsyncContinuationVarInfo
{
// IL number of variable (or one of the special IL numbers, like TYPECTXT_ILNUM)
uint32_t VarNumber;
// Offset in continuation object where this variable is stored
uint32_t Offset;
};

struct AsyncSuspensionPoint
{
// Offset of this suspension point's resumption point.
uint32_t NativeResumeOffset;
// Logical return address of the async call (join point of synchronous and resuming paths)
uint32_t NativeJoinOffset;
// Count of AsyncContinuationVarInfo in array of locals starting where
// the previous suspension point's locals end.
uint32_t NumContinuationVars;
};

struct AsyncInfo
{
// Number of suspension points in the method.
uint32_t NumSuspensionPoints;
};
};
10 changes: 10 additions & 0 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -2912,6 +2912,16 @@ class ICorStaticInfo
uint32_t numMappings // [IN] Number of rich mappings
) = 0;

// Report async debug information to EE.
// The arrays are expected to be allocated with allocateArray
// and ownership is transferred to the EE with this call.
virtual void reportAsyncDebugInfo(
ICorDebugInfo::AsyncInfo* asyncInfo, // [IN] Async method information
ICorDebugInfo::AsyncSuspensionPoint* suspensionPoints, // [IN] Array of async suspension points, indexed by state number
ICorDebugInfo::AsyncContinuationVarInfo* vars, // [IN] Array of async continuation variable info
uint32_t numVars // [IN] Number of entries in the async vars array
) = 0;

// Report back some metadata about the compilation to the EE -- for
// example, metrics about the compilation.
virtual void reportMetadata(
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/inc/icorjitinfoimpl_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,12 @@ void reportRichMappings(
ICorDebugInfo::RichOffsetMapping* mappings,
uint32_t numMappings) override;

void reportAsyncDebugInfo(
ICorDebugInfo::AsyncInfo* asyncInfo,
ICorDebugInfo::AsyncSuspensionPoint* suspensionPoints,
ICorDebugInfo::AsyncContinuationVarInfo* vars,
uint32_t numVars) override;

void reportMetadata(
const char* key,
const void* value,
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@

#include <minipal/guid.h>

constexpr GUID JITEEVersionIdentifier = { /* 68e93e9d-dd28-49ca-9ebc-a01a54532bb3 */
0x68e93e9d,
0xdd28,
0x49ca,
{0x9e, 0xbc, 0xa0, 0x1a, 0x54, 0x53, 0x2b, 0xb3}
constexpr GUID JITEEVersionIdentifier = { /* 590a21bb-2a2e-4b80-82dc-0bf1fd92a301 */
0x590a21bb,
0x2a2e,
0x4b80,
{0x82, 0xdc, 0x0b, 0xf1, 0xfd, 0x92, 0xa3, 0x01}
};

#endif // JIT_EE_VERSIONING_GUID_H
5 changes: 3 additions & 2 deletions src/coreclr/inc/readytorun.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
// src/coreclr/nativeaot/Runtime/inc/ModuleHeaders.h
// If you update this, ensure you run `git grep MINIMUM_READYTORUN_MAJOR_VERSION`
// and handle pending work.
#define READYTORUN_MAJOR_VERSION 16
#define READYTORUN_MAJOR_VERSION 17
#define READYTORUN_MINOR_VERSION 0x0000

#define MINIMUM_READYTORUN_MAJOR_VERSION 16
#define MINIMUM_READYTORUN_MAJOR_VERSION 17

// R2R Version 2.1 adds the InliningInfo section
// R2R Version 2.2 adds the ProfileDataInfo section
Expand All @@ -47,6 +47,7 @@
// R2R Version 14 changed x86 code generation to use funclets
// R2R Version 15 removes double to int/uint helper calls
// R2R Version 16 replaces the compression format for debug boundaries with a new format that is smaller and more efficient to parse
// R2R Version 17 adds support for producing "fat" debug information (that e.g. can include async debug info)

struct READYTORUN_CORE_HEADER
{
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/ICorJitInfo_names_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ DEF_CLR_API(setBoundaries)
DEF_CLR_API(getVars)
DEF_CLR_API(setVars)
DEF_CLR_API(reportRichMappings)
DEF_CLR_API(reportAsyncDebugInfo)
DEF_CLR_API(reportMetadata)
DEF_CLR_API(allocateArray)
DEF_CLR_API(freeArray)
Expand Down
11 changes: 11 additions & 0 deletions src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,17 @@ void WrapICorJitInfo::reportRichMappings(
API_LEAVE(reportRichMappings);
}

void WrapICorJitInfo::reportAsyncDebugInfo(
ICorDebugInfo::AsyncInfo* asyncInfo,
ICorDebugInfo::AsyncSuspensionPoint* suspensionPoints,
ICorDebugInfo::AsyncContinuationVarInfo* vars,
uint32_t numVars)
{
API_ENTER(reportAsyncDebugInfo);
wrapHnd->reportAsyncDebugInfo(asyncInfo, suspensionPoints, vars, numVars);
API_LEAVE(reportAsyncDebugInfo);
}

void WrapICorJitInfo::reportMetadata(
const char* key,
const void* value,
Expand Down
Loading
Loading