Skip to content
Open
Show file tree
Hide file tree
Changes from 38 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
16 changes: 8 additions & 8 deletions .github/prompts/add-new-jit-ee-api.prompt.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
---
mode: 'agent'
tools: ['githubRepo', 'codebase', 'terminalLastCommand']
tools: ['fetch', 'codebase', 'runCommands', 'usages', 'search', 'think']
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updating these tools based on @EgorBo's instructions (I used the prompt to add the JIT-EE boilerplate, but the agent was not making the changes automatically without allowing it access to these tools)

description: 'Add a new API to the JIT-VM (aka JIT-EE) interface in the codebase.'
---

#### 1 — Goal

Implement **one** new JIT-VM (also known as JIT-EE) API and all supporting glue.
Implement **one** new JIT-VM (also known as JIT-EE) API and all supporting glue.
The JIT-VM interface defines the APIs through which the JIT compiler communicates with the runtime (VM).

#### 2 — Prerequisites for the model

* You have full repo access
* You may run scripts (e.g., `.sh` or `.bat`)
* You may run scripts (e.g., `.sh` or `.bat`)
* Ask **clarifying questions** before the first code change if anything (signature, types, platform constraints) is unclear.

#### 3 — Required user inputs

Ask the user for a C-like signature of the new API if it's not provided.
Ask the user for a C-like signature of the new API if it's not provided.
Suggest `<repo_root>/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt` file as a reference. Example:

```
Expand Down Expand Up @@ -83,8 +83,8 @@ Use the correct directory for the script to run.
+}
```

6. Now implement the most complex part - SuperPMI. SuperPMI acts as a (de)serializer for JIT-VM queries in order
to then replay them without the actual VM to speed up jit-diffs and other scenarios. All parameters and return
6. Now implement the most complex part - SuperPMI. SuperPMI acts as a (de)serializer for JIT-VM queries in order
to then replay them without the actual VM to speed up jit-diffs and other scenarios. All parameters and return
values recorded/restored using special primitve types and helpers. We need to update the following files:

* `<repo_root>/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h`:
Expand All @@ -96,7 +96,7 @@ Go through each of them one by one.

* `<repo_root>/src/coreclr/tools/superpmi/superpmi-shared/agnostic.h`:
Define two `Agnostic_*` types for input arguments and another one for output parameters (return value, output arguments).
Do not create them if one of the generics ones can be re-used such as `DLD`, `DD`, `DLDL`, etc. Use `DWORD*`
Do not create them if one of the generics ones can be re-used such as `DLD`, `DD`, `DLDL`, etc. Use `DWORD*`
like types for integers. Inspect the whole file to see how other APIs are defined.

* `<repo_root>/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h`:
Expand Down Expand Up @@ -126,7 +126,7 @@ Now add a new element to `enum mcPackets` enum in the same file. Example:
```

* `<repo_root>/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp`:
Add the implementation of the 3 methods to `methodcontext.cpp` at the end of it.
Add the implementation of the 3 methods to `methodcontext.cpp` at the end of it.
Consider other similar methods in the file for reference. Do not change implementations of other methods in the file. Example:

```diff
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,8 @@ private interface IRuntimeAsyncTaskOps<T>
static abstract void PostToSyncContext(T task, SynchronizationContext syncCtx);
}

/// <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 @@ -310,9 +309,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 @@ -377,33 +375,53 @@ 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)
{
try
{
Continuation? newContinuation = continuation.Resume(continuation);
Continuation? curContinuation = continuation;
Debug.Assert(curContinuation != null);
Debug.Assert(curContinuation.Next != null);
continuation = curContinuation.Next;

Continuation? newContinuation = curContinuation.Resume(curContinuation);

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

Debug.Assert(continuation.Next != null);
continuation = continuation.Next;
}
catch (Exception ex)
{
Continuation nextContinuation = UnwindToPossibleHandler(continuation);
if (nextContinuation.Resume == null)
Continuation handlerContinuation = UnwindToPossibleHandler(continuation);
if (handlerContinuation.Resume == null)
{
// Tail of AsyncTaskMethodBuilderT.SetException
bool successfullySet = ex is OperationCanceledException oce ?
Expand All @@ -412,6 +430,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 @@ -420,9 +440,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.Resume == null)
Expand All @@ -431,6 +450,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 @@ -442,6 +463,7 @@ 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;
}
}
Expand All @@ -451,10 +473,11 @@ private static Continuation UnwindToPossibleHandler(Continuation continuation)
{
while (true)
{
Debug.Assert(continuation.Next != null);
continuation = continuation.Next;
if ((continuation.Flags & CorInfoContinuationFlags.CORINFO_CONTINUATION_NEEDS_EXCEPTION) != 0)
return continuation;

Debug.Assert(continuation.Next != null);
continuation = continuation.Next;
}
}

Expand Down Expand Up @@ -575,7 +598,7 @@ private static bool QueueContinuationFollowUpActionIfNecessary<T, TOps>(T task,
}
}

// Change return type to ThunkTask<T?> -- no benefit since this is used for Task returning thunks only
// Change return type to RuntimeAsyncTask<T?> -- no benefit since this is used for Task returning thunks only
#pragma warning disable CA1859
// When a Task-returning thunk gets a continuation result
// it calls here to make a Task that awaits on the current async state.
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
29 changes: 29 additions & 0 deletions src/coreclr/inc/cordebuginfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -431,4 +431,33 @@ 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;
// Index in continuation's byte[] data where this variable is stored, or 0xFFFFFFFF if the
// variable does not have any byte[] data
uint32_t Offset;
// Index in continuation's object[] data where this variable's GC pointers are stored, or 0xFFFFFFFF
// if the variable does not have any GC pointers
uint32_t GCIndex;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are emitting custom methodtables for the continuations, should we rather make the field layout flat and avoid these extra layers?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now Continuation is the same single type for all the uses:

internal sealed unsafe class Continuation
{
public Continuation? Next;
public delegate*<Continuation, Continuation?> Resume;
public uint State;
public CorInfoContinuationFlags Flags;
// Data and GCData contain the state of the continuation.
// Note: The JIT is ultimately responsible for laying out these arrays.
// However, other parts of the system depend on the layout to
// know where to locate or place various pieces of data:
//
// 1. Resumption stubs need to know where to place the return value
// inside the next continuation. If the return value has GC references
// then it is boxed and placed at GCData[0]; otherwise, it is placed
// inside Data at offset 0 if
// CORINFO_CONTINUATION_OSR_IL_OFFSET_IN_DATA is NOT set and otherwise
// at offset 4.
//
// 2. Likewise, Finalize[Value]TaskReturningThunk needs to know from
// where to extract the return value.
//
// 3. The dispatcher needs to know where to place the exception inside
// the next continuation with a handler. Continuations with handlers
// have CORINFO_CONTINUATION_NEEDS_EXCEPTION set. The exception is
// placed at GCData[0] if CORINFO_CONTINUATION_RESULT_IN_GCDATA is NOT
// set, and otherwise at GCData[1].
//
public byte[]? Data;
public object?[]? GCData;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have we done any modeling whether it is worth it to have the data in separate blocks from the continuation? The extra object headers and indirections are not free.

Copy link
Member

@VSadov VSadov Oct 7, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The design makes Continuation shape mostly opaque. Most helpers and the infrastructure do not dig into internals of Continuation. As long as JIT is self-consistent in terms of serialization/deserialization of locals, most other things are not concerned with the shape thus JIT can change the continuation shape, modulo R2R and debug interfaces.

There are just a few things that are meaningful to the infrastructure - the link to the Next continuation, the flags, the locations of the return value or an exception when infrastructure, upon completion of the calee, needs to place results into the caller's continuation before resuming it.
How most of the locals are stored is an opaque agreement between the method who serializes locals into a continuation and the method who deserializes - that is the same method.

Currently we use two arrays (array of bytes + array of objects) to serialize/deserialize locals. The biggest advantage is "time-to-market", obviously.
There are other advantages - like there is no type or GC layout generation. The shape of continuation is different for every await, so it is useful to only emit site-specific code, as we must do anyways, but not types/layouts. There could be more than one await per method so it could add up. We optimize for suspensions never happening though, statistically speaking, so slightly less efficient format which has fewer upfront/static requirements is attractive.

There are disadvantages:

  • it is not the most compact format. Think of capturing just one int and one object.
  • return values that happen to be object-containing structs, need to be boxed.
  • Also it could be difficult to external introspection like a debugger.
    For example structs containing a mix of int and object fields get their fields stored in different arrays accordingly. It is not a problem for JIT to reconstitute such struct, but it could be an inconvenience for other observers.

Anyways. The API here tries to support the current format, but leave the door open for future changes.
I think it is good to not have too many parts changing at once, unless it is blocking or costly to change later, so I think it is a good approach even if we think of tweaking the continuation format.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we are emitting custom methodtables for the continuations, should we rather make the field layout flat and avoid these extra layers?

Yes, once/if #120411 makes it in, we only need Offset here.

Originally I didn't add GCIndex for precisely the reason that I expected we would do that. However @tommcdon was playing around with the debug info earlier and wondered about the data he was seeing, and since it's not a large change I decided to just add it for now, with the catch that it might change in the future.

I agree with all of @VSadov's points, but we probably need to measure it. I also am somewhat worried about creating custom MethodTable for every continuation up front. Although the actual creation in #120411 is lightweight so maybe it will not be a problem.
In the end we could even take a hybrid approach with the byte[]/object[] version used for tier0/debug and the flat versions used for tier1. Of course that makes it more complicated for everyone since now they need to be aware of two possible formats.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example structs containing a mix of int and object fields get their fields stored in different arrays accordingly. It is not a problem for JIT to reconstitute such struct, but it could be an inconvenience for other observers.

Is there a design for how the debugger could reconstitute such a struct? It doesn't seem like the current debug info is sufficiently powerful to represent that.

The API here tries to support the current format, but leave the door open for future changes.

If you'd like to leave the door open to store locals inline within the Continuation rather than indirected, perhaps represent the variable location as:

        enum Base
        {
            ContinuationObj = 1, // variable stored at continuation + offset
            DataArray = 2,       // variable stored at continuation->Data + offset
            GCDataArray = 3      // variable stored at continuation->GCData + offset
        }
        Base OffsetBase;
        uint32_t Offset;

Alternately changing the contract sometime in the next 6 months probably isn't too costly. Doing it close to .NET 11 ship or after .NET 11 ship would have additional burdens.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a design for how the debugger could reconstitute such a struct? It doesn't seem like the current debug info is sufficiently powerful to represent that.

The replicate the way the JIT currently stores/restores these values, for a type of size S:

  1. If Offset != UINT_MAX, take S bytes from Data starting from Offset
  2. If GCIndex != UINT_MAX, fill in the GC pointers in ascending order of offset in the type, starting with the GC pointer at index GCIndex

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If debuggers hard-code that algorithm it becomes a breaking change if the JIT ever wants to lay out the data differently. Is this an algorithm we want to set in stone or just a stop-gap for now? I haven't had a chance to get a good look at #120411 yet but it suggests our plans for field layout are still in flux.

In that algorithm above, do we have to worry about alignment padding or all the fields will be packed?

Copy link
Member Author

@jakobbotsch jakobbotsch Oct 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this an algorithm we want to set in stone or just a stop-gap for now?

At this point I am expecting/hopeful that #120411 makes it in. It makes things simpler -- a single offset and the type is just stored in the normal way at that offset in the continuation. But it has other implications for various components as @davidwrighton pointed out in that PR.

The current storage mechanism exists almost unchanged since the original prototype in 2023. It was the simplest thing I could think of that didn't require boxing all structs with object fields in them.

In that algorithm above, do we have to worry about alignment padding or all the fields will be packed?

Do you mean for step 2? The GCIndex encodes an index into the GCData array. If the value has N object refs in it, then GCData will store N object refs starting at that index. However, it will be up to the reconstruction code to figure out where those N object refs are stored in the value and to copy the GC refs from GCData across.

There can be alignment padding in Data to make sure value types are aligned properly but reconstruction doesn't need to worry about that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still have a little confusion about the current algorithm, but since it doesn't look like we'll be keeping it much longer no need for me to suss out the details :) I'm assuming the new continuation types will trigger a new round of updates here.

};

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 = { /* 3d2bdd20-eced-4a07-b9fb-227ce7f55fcd */
0x3d2bdd20,
0xeced,
0x4a07,
{0xb9, 0xfb, 0x22, 0x7c, 0xe7, 0xf5, 0x5f, 0xcd}
constexpr GUID JITEEVersionIdentifier = { /* 421f544d-55cb-4e2a-a43d-c308a8c071d7 */
0x421f544d,
0x55cb,
0x4e2a,
{0xa4, 0x3d, 0xc3, 0x08, 0xa8, 0xc0, 0x71, 0xd7}
};

#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