Convert priority 3 MethodDescCallSite calls to UnmanagedCallersOnly - #124854

Merged
steveisok merged 24 commits into
dotnet:mainfrom
steveisok:uco-excep-p3
Mar 6, 2026
Merged

Convert priority 3 MethodDescCallSite calls to UnmanagedCallersOnly#124854
steveisok merged 24 commits into
dotnet:mainfrom
steveisok:uco-excep-p3

Conversation

@steveisok

Copy link
Copy Markdown
Member

First set of priority 3 conversions from #123864 — replace MethodDescCallSite/CallDescrWorker calls with UnmanagedCallersOnly reverse P/Invoke calls.

Converted call sites

FileCall siteMethod
appdomain.cppAppDomain::RaiseExitProcessEventON_PROCESS_EXIT
appdomain.cppAppDomain::OnUnhandledExceptionON_UNHANDLED_EXCEPTION
assembly.cppRunManagedStartupMANAGED_STARTUP
assembly.cppRunMainInternal (TARGET_BROWSER)HANDLE_ASYNC_ENTRYPOINT
invokeutil.cppInvokeUtil::CreateClassLoadExceptReflectionTypeLoadException ctor
invokeutil.cppInvokeUtil::CreateTargetExceptTargetInvocationException ctor

Remaining priority 3 items (follow ups)

  • Main entry point in RunMainInternal (dynamic MethodDesc)
  • CustomAttribute_CreateCustomAttributeInstance (dynamic ctor, already a QCall)
  • CorHost2::ExecuteAssembly (dynamic method lookup)
  • FuncEvalWrapper/DoNormalFuncEval (debugger func-eval)

Pattern

Follows the same conversion pattern as #124834 (priority 2). Each conversion adds an [UnmanagedCallersOnly] managed wrapper with an Exception* out-parameter and replaces the native MethodDescCallSite + ARG_SLOT with
UnmanagedCallersOnlyCaller::InvokeThrowing.

Replace MethodDescCallSite/CallDescrWorker calls with more efficient
UnmanagedCallersOnly reverse P/Invoke calls for priority 3 items from
dotnet#123864.
Converted call sites:
- AppDomain::RaiseExitProcessEvent (ON_PROCESS_EXIT)
- AppDomain::OnUnhandledException (ON_UNHANDLED_EXCEPTION)
- RunManagedStartup (MANAGED_STARTUP)
- RunMainInternal async helpers (HANDLE_ASYNC_ENTRYPOINT, TARGET_BROWSER)
- InvokeUtil::CreateClassLoadExcept (ReflectionTypeLoadException ctor)
- InvokeUtil::CreateTargetExcept (TargetInvocationException ctor)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Comment threadsrc/coreclr/vm/invokeutil.cpp Outdated
…-param and managed GetDefinedTypes() throws ReflectionTypeLoadException. Deleted reateClassLoadExcept + UCO wrapper + metasig as a result.
Adjusted OnUnhandledException in AppContext.CoreCLR.cs to use a bare catch based on feedback.
CopilotAI review requested due to automatic review settings February 25, 2026 16:49

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR converts priority 3 MethodDescCallSite/CallDescrWorker calls to more efficient UnmanagedCallersOnly reverse P/Invoke calls, following the established pattern from PR #124834. The conversions target application entry points and process lifecycle events in CoreCLR.

Changes:

  • Adds [UnmanagedCallersOnly] wrappers in managed code with Exception* out-parameters for exception propagation
  • Replaces native MethodDescCallSite calls with UnmanagedCallersOnlyCaller::InvokeThrowing template class
  • Refactors ReflectionTypeLoadException creation from native to managed code via QCall pattern

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.Browser.csAdds UCO wrapper for HandleAsyncEntryPoint to handle async Main entry points on Browser target
src/coreclr/System.Private.CoreLib/src/System/StartupHookProvider.CoreCLR.csAdds UCO wrapper for ManagedStartup with exception handling
src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.csAdds UCO wrapper for CreateTargetInvocationException
src/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.csNew file with UCO wrappers for OnProcessExit and OnUnhandledException
src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.csUpdates GetTypes QCall to return exceptions array for managed-side exception construction
src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csprojAdds new AppContext.CoreCLR.cs file to build
src/coreclr/vm/metasig.hAdds new metasig definitions for UCO method signatures
src/coreclr/vm/corelib.hUpdates DEFINE_METHOD entries to reference new UCO signatures
src/coreclr/vm/appdomain.cppReplaces MethodDescCallSite with UnmanagedCallersOnlyCaller for process lifecycle events
src/coreclr/vm/assembly.cppReplaces MethodDescCallSite with UnmanagedCallersOnlyCaller for startup hooks and async entry points
src/coreclr/vm/invokeutil.hRemoves obsolete CreateClassLoadExcept declaration
src/coreclr/vm/invokeutil.cppRemoves CreateClassLoadExcept implementation; converts CreateTargetExcept to use UCO pattern
src/coreclr/vm/commodule.hAdds retExceptions parameter to RuntimeModule_GetTypes QCall signature
src/coreclr/vm/commodule.cppReturns exceptions array via out-parameter instead of throwing from native code
src/coreclr/vm/exceptionhandlingqcalls.hFormatting fix - adds blank line at end of file

CopilotAI review requested due to automatic review settings February 25, 2026 18:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/coreclr/vm/commodule.cpp:766

  • RuntimeModule_GetTypes no longer throws inside the QCall when type loading fails, but the loop still doesn’t advance curPos on failure. With retExceptions.Set(...) replacing the throw, execution now continues and will hit _ASSERTE(curPos == dwNumTypeDefs) when any type load fails. Adjust the loop to keep curPos in sync with dwNumTypeDefs (e.g., advance and leave a null slot for failed loads, or remove/replace the assertion and ensure the returned Types array matches the intended semantics).
 // Return exceptions to managed side for throwing
if (cXcept > 0) {
gc.xceptRet = (PTRARRAYREF) AllocateObjectArray(cXcept,g_pExceptionClass);
for (DWORD i=0;i<cXcept;i++) {
gc.xceptRet->SetAt(i, gc.xcept->GetAt(i));
}
retExceptions.Set(gc.xceptRet);
}
// We should have filled the array exactly.
_ASSERTE(curPos == dwNumTypeDefs);

Comment threadsrc/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs Outdated
Comment threadsrc/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs Outdated
Comment threadsrc/coreclr/vm/invokeutil.cpp Outdated
Comment threadsrc/coreclr/vm/invokeutil.cpp
@jkotas

Copy link
Copy Markdown
Member

Test failure

ASSERT FAILED
Expression: curPos == dwNumTypeDefs
Location: /__w/1/s/src/coreclr/vm/commodule.cpp:765
Function: RuntimeModule_GetTypes
Process: 84956

Comment threadsrc/coreclr/vm/commodule.cpp
@jkotas

Copy link
Copy Markdown
Member

The wasm temporary callhelpers needs to be regenerated as part of these PRs: https://github.com/dotnet/runtime/blob/main/docs/workflow/wasm-documentation.md#running-coreclr-callhelpers-generator

CopilotAI review requested due to automatic review settings March 2, 2026 16:40

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/assembly.cpp
CopilotAI review requested due to automatic review settings March 5, 2026 15:57

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.


You can also share your feedback on Copilot code review. Take the survey.

Comment threadsrc/coreclr/vm/corelib.h
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@steveisok@jkotas@pavelsavara@radekdoulik@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Convert priority 3 MethodDescCallSite calls to UnmanagedCallersOnly - #124854

Merged
steveisok merged 24 commits into
dotnet:mainfrom
steveisok:uco-excep-p3
Mar 6, 2026
Merged

Convert priority 3 MethodDescCallSite calls to UnmanagedCallersOnly#124854
steveisok merged 24 commits into
dotnet:mainfrom
steveisok:uco-excep-p3

Conversation

@steveisok

Copy link
Copy Markdown
Member

First set of priority 3 conversions from #123864 — replace MethodDescCallSite/CallDescrWorker calls with UnmanagedCallersOnly reverse P/Invoke calls.

Converted call sites

FileCall siteMethod
appdomain.cppAppDomain::RaiseExitProcessEventON_PROCESS_EXIT
appdomain.cppAppDomain::OnUnhandledExceptionON_UNHANDLED_EXCEPTION
assembly.cppRunManagedStartupMANAGED_STARTUP
assembly.cppRunMainInternal (TARGET_BROWSER)HANDLE_ASYNC_ENTRYPOINT
invokeutil.cppInvokeUtil::CreateClassLoadExceptReflectionTypeLoadException ctor
invokeutil.cppInvokeUtil::CreateTargetExceptTargetInvocationException ctor

Remaining priority 3 items (follow ups)

  • Main entry point in RunMainInternal (dynamic MethodDesc)
  • CustomAttribute_CreateCustomAttributeInstance (dynamic ctor, already a QCall)
  • CorHost2::ExecuteAssembly (dynamic method lookup)
  • FuncEvalWrapper/DoNormalFuncEval (debugger func-eval)

Pattern

Follows the same conversion pattern as #124834 (priority 2). Each conversion adds an [UnmanagedCallersOnly] managed wrapper with an Exception* out-parameter and replaces the native MethodDescCallSite + ARG_SLOT with
UnmanagedCallersOnlyCaller::InvokeThrowing.

Replace MethodDescCallSite/CallDescrWorker calls with more efficient
UnmanagedCallersOnly reverse P/Invoke calls for priority 3 items from
dotnet#123864.
Converted call sites:
- AppDomain::RaiseExitProcessEvent (ON_PROCESS_EXIT)
- AppDomain::OnUnhandledException (ON_UNHANDLED_EXCEPTION)
- RunManagedStartup (MANAGED_STARTUP)
- RunMainInternal async helpers (HANDLE_ASYNC_ENTRYPOINT, TARGET_BROWSER)
- InvokeUtil::CreateClassLoadExcept (ReflectionTypeLoadException ctor)
- InvokeUtil::CreateTargetExcept (TargetInvocationException ctor)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Comment threadsrc/coreclr/vm/invokeutil.cpp Outdated
…-param and managed GetDefinedTypes() throws ReflectionTypeLoadException. Deleted reateClassLoadExcept + UCO wrapper + metasig as a result.
Adjusted OnUnhandledException in AppContext.CoreCLR.cs to use a bare catch based on feedback.
CopilotAI review requested due to automatic review settings February 25, 2026 16:49

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR converts priority 3 MethodDescCallSite/CallDescrWorker calls to more efficient UnmanagedCallersOnly reverse P/Invoke calls, following the established pattern from PR #124834. The conversions target application entry points and process lifecycle events in CoreCLR.

Changes:

  • Adds [UnmanagedCallersOnly] wrappers in managed code with Exception* out-parameters for exception propagation
  • Replaces native MethodDescCallSite calls with UnmanagedCallersOnlyCaller::InvokeThrowing template class
  • Refactors ReflectionTypeLoadException creation from native to managed code via QCall pattern

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.Browser.csAdds UCO wrapper for HandleAsyncEntryPoint to handle async Main entry points on Browser target
src/coreclr/System.Private.CoreLib/src/System/StartupHookProvider.CoreCLR.csAdds UCO wrapper for ManagedStartup with exception handling
src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.csAdds UCO wrapper for CreateTargetInvocationException
src/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.csNew file with UCO wrappers for OnProcessExit and OnUnhandledException
src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.csUpdates GetTypes QCall to return exceptions array for managed-side exception construction
src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csprojAdds new AppContext.CoreCLR.cs file to build
src/coreclr/vm/metasig.hAdds new metasig definitions for UCO method signatures
src/coreclr/vm/corelib.hUpdates DEFINE_METHOD entries to reference new UCO signatures
src/coreclr/vm/appdomain.cppReplaces MethodDescCallSite with UnmanagedCallersOnlyCaller for process lifecycle events
src/coreclr/vm/assembly.cppReplaces MethodDescCallSite with UnmanagedCallersOnlyCaller for startup hooks and async entry points
src/coreclr/vm/invokeutil.hRemoves obsolete CreateClassLoadExcept declaration
src/coreclr/vm/invokeutil.cppRemoves CreateClassLoadExcept implementation; converts CreateTargetExcept to use UCO pattern
src/coreclr/vm/commodule.hAdds retExceptions parameter to RuntimeModule_GetTypes QCall signature
src/coreclr/vm/commodule.cppReturns exceptions array via out-parameter instead of throwing from native code
src/coreclr/vm/exceptionhandlingqcalls.hFormatting fix - adds blank line at end of file

CopilotAI review requested due to automatic review settings February 25, 2026 18:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/coreclr/vm/commodule.cpp:766

  • RuntimeModule_GetTypes no longer throws inside the QCall when type loading fails, but the loop still doesn’t advance curPos on failure. With retExceptions.Set(...) replacing the throw, execution now continues and will hit _ASSERTE(curPos == dwNumTypeDefs) when any type load fails. Adjust the loop to keep curPos in sync with dwNumTypeDefs (e.g., advance and leave a null slot for failed loads, or remove/replace the assertion and ensure the returned Types array matches the intended semantics).
 // Return exceptions to managed side for throwing
if (cXcept > 0) {
gc.xceptRet = (PTRARRAYREF) AllocateObjectArray(cXcept,g_pExceptionClass);
for (DWORD i=0;i<cXcept;i++) {
gc.xceptRet->SetAt(i, gc.xcept->GetAt(i));
}
retExceptions.Set(gc.xceptRet);
}
// We should have filled the array exactly.
_ASSERTE(curPos == dwNumTypeDefs);

Comment threadsrc/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs Outdated
Comment threadsrc/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs Outdated
Comment threadsrc/coreclr/vm/invokeutil.cpp Outdated
Comment threadsrc/coreclr/vm/invokeutil.cpp
@jkotas

Copy link
Copy Markdown
Member

Test failure

ASSERT FAILED
Expression: curPos == dwNumTypeDefs
Location: /__w/1/s/src/coreclr/vm/commodule.cpp:765
Function: RuntimeModule_GetTypes
Process: 84956

Comment threadsrc/coreclr/vm/commodule.cpp
@jkotas

Copy link
Copy Markdown
Member

The wasm temporary callhelpers needs to be regenerated as part of these PRs: https://github.com/dotnet/runtime/blob/main/docs/workflow/wasm-documentation.md#running-coreclr-callhelpers-generator

CopilotAI review requested due to automatic review settings March 2, 2026 16:40

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/assembly.cpp
CopilotAI review requested due to automatic review settings March 5, 2026 15:57

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.


You can also share your feedback on Copilot code review. Take the survey.

Comment threadsrc/coreclr/vm/corelib.h
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@steveisok@jkotas@pavelsavara@radekdoulik@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Convert priority 3 MethodDescCallSite calls to UnmanagedCallersOnly - #124854

Merged
steveisok merged 24 commits into
dotnet:mainfrom
steveisok:uco-excep-p3
Mar 6, 2026
Merged

Convert priority 3 MethodDescCallSite calls to UnmanagedCallersOnly#124854
steveisok merged 24 commits into
dotnet:mainfrom
steveisok:uco-excep-p3

Conversation

@steveisok

Copy link
Copy Markdown
Member

First set of priority 3 conversions from #123864 — replace MethodDescCallSite/CallDescrWorker calls with UnmanagedCallersOnly reverse P/Invoke calls.

Converted call sites

FileCall siteMethod
appdomain.cppAppDomain::RaiseExitProcessEventON_PROCESS_EXIT
appdomain.cppAppDomain::OnUnhandledExceptionON_UNHANDLED_EXCEPTION
assembly.cppRunManagedStartupMANAGED_STARTUP
assembly.cppRunMainInternal (TARGET_BROWSER)HANDLE_ASYNC_ENTRYPOINT
invokeutil.cppInvokeUtil::CreateClassLoadExceptReflectionTypeLoadException ctor
invokeutil.cppInvokeUtil::CreateTargetExceptTargetInvocationException ctor

Remaining priority 3 items (follow ups)

  • Main entry point in RunMainInternal (dynamic MethodDesc)
  • CustomAttribute_CreateCustomAttributeInstance (dynamic ctor, already a QCall)
  • CorHost2::ExecuteAssembly (dynamic method lookup)
  • FuncEvalWrapper/DoNormalFuncEval (debugger func-eval)

Pattern

Follows the same conversion pattern as #124834 (priority 2). Each conversion adds an [UnmanagedCallersOnly] managed wrapper with an Exception* out-parameter and replaces the native MethodDescCallSite + ARG_SLOT with
UnmanagedCallersOnlyCaller::InvokeThrowing.

Replace MethodDescCallSite/CallDescrWorker calls with more efficient
UnmanagedCallersOnly reverse P/Invoke calls for priority 3 items from
dotnet#123864.
Converted call sites:
- AppDomain::RaiseExitProcessEvent (ON_PROCESS_EXIT)
- AppDomain::OnUnhandledException (ON_UNHANDLED_EXCEPTION)
- RunManagedStartup (MANAGED_STARTUP)
- RunMainInternal async helpers (HANDLE_ASYNC_ENTRYPOINT, TARGET_BROWSER)
- InvokeUtil::CreateClassLoadExcept (ReflectionTypeLoadException ctor)
- InvokeUtil::CreateTargetExcept (TargetInvocationException ctor)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Comment threadsrc/coreclr/vm/invokeutil.cpp Outdated
…-param and managed GetDefinedTypes() throws ReflectionTypeLoadException. Deleted reateClassLoadExcept + UCO wrapper + metasig as a result.
Adjusted OnUnhandledException in AppContext.CoreCLR.cs to use a bare catch based on feedback.
CopilotAI review requested due to automatic review settings February 25, 2026 16:49

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR converts priority 3 MethodDescCallSite/CallDescrWorker calls to more efficient UnmanagedCallersOnly reverse P/Invoke calls, following the established pattern from PR #124834. The conversions target application entry points and process lifecycle events in CoreCLR.

Changes:

  • Adds [UnmanagedCallersOnly] wrappers in managed code with Exception* out-parameters for exception propagation
  • Replaces native MethodDescCallSite calls with UnmanagedCallersOnlyCaller::InvokeThrowing template class
  • Refactors ReflectionTypeLoadException creation from native to managed code via QCall pattern

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.Browser.csAdds UCO wrapper for HandleAsyncEntryPoint to handle async Main entry points on Browser target
src/coreclr/System.Private.CoreLib/src/System/StartupHookProvider.CoreCLR.csAdds UCO wrapper for ManagedStartup with exception handling
src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.csAdds UCO wrapper for CreateTargetInvocationException
src/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.csNew file with UCO wrappers for OnProcessExit and OnUnhandledException
src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.csUpdates GetTypes QCall to return exceptions array for managed-side exception construction
src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csprojAdds new AppContext.CoreCLR.cs file to build
src/coreclr/vm/metasig.hAdds new metasig definitions for UCO method signatures
src/coreclr/vm/corelib.hUpdates DEFINE_METHOD entries to reference new UCO signatures
src/coreclr/vm/appdomain.cppReplaces MethodDescCallSite with UnmanagedCallersOnlyCaller for process lifecycle events
src/coreclr/vm/assembly.cppReplaces MethodDescCallSite with UnmanagedCallersOnlyCaller for startup hooks and async entry points
src/coreclr/vm/invokeutil.hRemoves obsolete CreateClassLoadExcept declaration
src/coreclr/vm/invokeutil.cppRemoves CreateClassLoadExcept implementation; converts CreateTargetExcept to use UCO pattern
src/coreclr/vm/commodule.hAdds retExceptions parameter to RuntimeModule_GetTypes QCall signature
src/coreclr/vm/commodule.cppReturns exceptions array via out-parameter instead of throwing from native code
src/coreclr/vm/exceptionhandlingqcalls.hFormatting fix - adds blank line at end of file

CopilotAI review requested due to automatic review settings February 25, 2026 18:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/coreclr/vm/commodule.cpp:766

  • RuntimeModule_GetTypes no longer throws inside the QCall when type loading fails, but the loop still doesn’t advance curPos on failure. With retExceptions.Set(...) replacing the throw, execution now continues and will hit _ASSERTE(curPos == dwNumTypeDefs) when any type load fails. Adjust the loop to keep curPos in sync with dwNumTypeDefs (e.g., advance and leave a null slot for failed loads, or remove/replace the assertion and ensure the returned Types array matches the intended semantics).
 // Return exceptions to managed side for throwing
if (cXcept > 0) {
gc.xceptRet = (PTRARRAYREF) AllocateObjectArray(cXcept,g_pExceptionClass);
for (DWORD i=0;i<cXcept;i++) {
gc.xceptRet->SetAt(i, gc.xcept->GetAt(i));
}
retExceptions.Set(gc.xceptRet);
}
// We should have filled the array exactly.
_ASSERTE(curPos == dwNumTypeDefs);

Comment threadsrc/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs Outdated
Comment threadsrc/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs Outdated
Comment threadsrc/coreclr/vm/invokeutil.cpp Outdated
Comment threadsrc/coreclr/vm/invokeutil.cpp
@jkotas

Copy link
Copy Markdown
Member

Test failure

ASSERT FAILED
Expression: curPos == dwNumTypeDefs
Location: /__w/1/s/src/coreclr/vm/commodule.cpp:765
Function: RuntimeModule_GetTypes
Process: 84956

Comment threadsrc/coreclr/vm/commodule.cpp
@jkotas

Copy link
Copy Markdown
Member

The wasm temporary callhelpers needs to be regenerated as part of these PRs: https://github.com/dotnet/runtime/blob/main/docs/workflow/wasm-documentation.md#running-coreclr-callhelpers-generator

CopilotAI review requested due to automatic review settings March 2, 2026 16:40

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/assembly.cpp
CopilotAI review requested due to automatic review settings March 5, 2026 15:57

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.


You can also share your feedback on Copilot code review. Take the survey.

Comment threadsrc/coreclr/vm/corelib.h
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@steveisok@jkotas@pavelsavara@radekdoulik@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Convert priority 3 MethodDescCallSite calls to UnmanagedCallersOnly - #124854

Merged
steveisok merged 24 commits into
dotnet:mainfrom
steveisok:uco-excep-p3
Mar 6, 2026
Merged

Convert priority 3 MethodDescCallSite calls to UnmanagedCallersOnly#124854
steveisok merged 24 commits into
dotnet:mainfrom
steveisok:uco-excep-p3

Conversation

@steveisok

Copy link
Copy Markdown
Member

First set of priority 3 conversions from #123864 — replace MethodDescCallSite/CallDescrWorker calls with UnmanagedCallersOnly reverse P/Invoke calls.

Converted call sites

FileCall siteMethod
appdomain.cppAppDomain::RaiseExitProcessEventON_PROCESS_EXIT
appdomain.cppAppDomain::OnUnhandledExceptionON_UNHANDLED_EXCEPTION
assembly.cppRunManagedStartupMANAGED_STARTUP
assembly.cppRunMainInternal (TARGET_BROWSER)HANDLE_ASYNC_ENTRYPOINT
invokeutil.cppInvokeUtil::CreateClassLoadExceptReflectionTypeLoadException ctor
invokeutil.cppInvokeUtil::CreateTargetExceptTargetInvocationException ctor

Remaining priority 3 items (follow ups)

  • Main entry point in RunMainInternal (dynamic MethodDesc)
  • CustomAttribute_CreateCustomAttributeInstance (dynamic ctor, already a QCall)
  • CorHost2::ExecuteAssembly (dynamic method lookup)
  • FuncEvalWrapper/DoNormalFuncEval (debugger func-eval)

Pattern

Follows the same conversion pattern as #124834 (priority 2). Each conversion adds an [UnmanagedCallersOnly] managed wrapper with an Exception* out-parameter and replaces the native MethodDescCallSite + ARG_SLOT with
UnmanagedCallersOnlyCaller::InvokeThrowing.

Replace MethodDescCallSite/CallDescrWorker calls with more efficient
UnmanagedCallersOnly reverse P/Invoke calls for priority 3 items from
dotnet#123864.
Converted call sites:
- AppDomain::RaiseExitProcessEvent (ON_PROCESS_EXIT)
- AppDomain::OnUnhandledException (ON_UNHANDLED_EXCEPTION)
- RunManagedStartup (MANAGED_STARTUP)
- RunMainInternal async helpers (HANDLE_ASYNC_ENTRYPOINT, TARGET_BROWSER)
- InvokeUtil::CreateClassLoadExcept (ReflectionTypeLoadException ctor)
- InvokeUtil::CreateTargetExcept (TargetInvocationException ctor)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Comment threadsrc/coreclr/vm/invokeutil.cpp Outdated
…-param and managed GetDefinedTypes() throws ReflectionTypeLoadException. Deleted reateClassLoadExcept + UCO wrapper + metasig as a result.
Adjusted OnUnhandledException in AppContext.CoreCLR.cs to use a bare catch based on feedback.
CopilotAI review requested due to automatic review settings February 25, 2026 16:49

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR converts priority 3 MethodDescCallSite/CallDescrWorker calls to more efficient UnmanagedCallersOnly reverse P/Invoke calls, following the established pattern from PR #124834. The conversions target application entry points and process lifecycle events in CoreCLR.

Changes:

  • Adds [UnmanagedCallersOnly] wrappers in managed code with Exception* out-parameters for exception propagation
  • Replaces native MethodDescCallSite calls with UnmanagedCallersOnlyCaller::InvokeThrowing template class
  • Refactors ReflectionTypeLoadException creation from native to managed code via QCall pattern

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.Browser.csAdds UCO wrapper for HandleAsyncEntryPoint to handle async Main entry points on Browser target
src/coreclr/System.Private.CoreLib/src/System/StartupHookProvider.CoreCLR.csAdds UCO wrapper for ManagedStartup with exception handling
src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.csAdds UCO wrapper for CreateTargetInvocationException
src/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.csNew file with UCO wrappers for OnProcessExit and OnUnhandledException
src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.csUpdates GetTypes QCall to return exceptions array for managed-side exception construction
src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csprojAdds new AppContext.CoreCLR.cs file to build
src/coreclr/vm/metasig.hAdds new metasig definitions for UCO method signatures
src/coreclr/vm/corelib.hUpdates DEFINE_METHOD entries to reference new UCO signatures
src/coreclr/vm/appdomain.cppReplaces MethodDescCallSite with UnmanagedCallersOnlyCaller for process lifecycle events
src/coreclr/vm/assembly.cppReplaces MethodDescCallSite with UnmanagedCallersOnlyCaller for startup hooks and async entry points
src/coreclr/vm/invokeutil.hRemoves obsolete CreateClassLoadExcept declaration
src/coreclr/vm/invokeutil.cppRemoves CreateClassLoadExcept implementation; converts CreateTargetExcept to use UCO pattern
src/coreclr/vm/commodule.hAdds retExceptions parameter to RuntimeModule_GetTypes QCall signature
src/coreclr/vm/commodule.cppReturns exceptions array via out-parameter instead of throwing from native code
src/coreclr/vm/exceptionhandlingqcalls.hFormatting fix - adds blank line at end of file

CopilotAI review requested due to automatic review settings February 25, 2026 18:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/coreclr/vm/commodule.cpp:766

  • RuntimeModule_GetTypes no longer throws inside the QCall when type loading fails, but the loop still doesn’t advance curPos on failure. With retExceptions.Set(...) replacing the throw, execution now continues and will hit _ASSERTE(curPos == dwNumTypeDefs) when any type load fails. Adjust the loop to keep curPos in sync with dwNumTypeDefs (e.g., advance and leave a null slot for failed loads, or remove/replace the assertion and ensure the returned Types array matches the intended semantics).
 // Return exceptions to managed side for throwing
if (cXcept > 0) {
gc.xceptRet = (PTRARRAYREF) AllocateObjectArray(cXcept,g_pExceptionClass);
for (DWORD i=0;i<cXcept;i++) {
gc.xceptRet->SetAt(i, gc.xcept->GetAt(i));
}
retExceptions.Set(gc.xceptRet);
}
// We should have filled the array exactly.
_ASSERTE(curPos == dwNumTypeDefs);

Comment threadsrc/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs Outdated
Comment threadsrc/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs Outdated
Comment threadsrc/coreclr/vm/invokeutil.cpp Outdated
Comment threadsrc/coreclr/vm/invokeutil.cpp
@jkotas

Copy link
Copy Markdown
Member

Test failure

ASSERT FAILED
Expression: curPos == dwNumTypeDefs
Location: /__w/1/s/src/coreclr/vm/commodule.cpp:765
Function: RuntimeModule_GetTypes
Process: 84956

Comment threadsrc/coreclr/vm/commodule.cpp
@jkotas

Copy link
Copy Markdown
Member

The wasm temporary callhelpers needs to be regenerated as part of these PRs: https://github.com/dotnet/runtime/blob/main/docs/workflow/wasm-documentation.md#running-coreclr-callhelpers-generator

CopilotAI review requested due to automatic review settings March 2, 2026 16:40

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/assembly.cpp
CopilotAI review requested due to automatic review settings March 5, 2026 15:57

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.


You can also share your feedback on Copilot code review. Take the survey.

Comment threadsrc/coreclr/vm/corelib.h
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@steveisok@jkotas@pavelsavara@radekdoulik@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Convert priority 3 MethodDescCallSite calls to UnmanagedCallersOnly - #124854

Merged
steveisok merged 24 commits into
dotnet:mainfrom
steveisok:uco-excep-p3
Mar 6, 2026
Merged

Convert priority 3 MethodDescCallSite calls to UnmanagedCallersOnly#124854
steveisok merged 24 commits into
dotnet:mainfrom
steveisok:uco-excep-p3

Conversation

@steveisok

Copy link
Copy Markdown
Member

First set of priority 3 conversions from #123864 — replace MethodDescCallSite/CallDescrWorker calls with UnmanagedCallersOnly reverse P/Invoke calls.

Converted call sites

FileCall siteMethod
appdomain.cppAppDomain::RaiseExitProcessEventON_PROCESS_EXIT
appdomain.cppAppDomain::OnUnhandledExceptionON_UNHANDLED_EXCEPTION
assembly.cppRunManagedStartupMANAGED_STARTUP
assembly.cppRunMainInternal (TARGET_BROWSER)HANDLE_ASYNC_ENTRYPOINT
invokeutil.cppInvokeUtil::CreateClassLoadExceptReflectionTypeLoadException ctor
invokeutil.cppInvokeUtil::CreateTargetExceptTargetInvocationException ctor

Remaining priority 3 items (follow ups)

  • Main entry point in RunMainInternal (dynamic MethodDesc)
  • CustomAttribute_CreateCustomAttributeInstance (dynamic ctor, already a QCall)
  • CorHost2::ExecuteAssembly (dynamic method lookup)
  • FuncEvalWrapper/DoNormalFuncEval (debugger func-eval)

Pattern

Follows the same conversion pattern as #124834 (priority 2). Each conversion adds an [UnmanagedCallersOnly] managed wrapper with an Exception* out-parameter and replaces the native MethodDescCallSite + ARG_SLOT with
UnmanagedCallersOnlyCaller::InvokeThrowing.

Replace MethodDescCallSite/CallDescrWorker calls with more efficient
UnmanagedCallersOnly reverse P/Invoke calls for priority 3 items from
dotnet#123864.
Converted call sites:
- AppDomain::RaiseExitProcessEvent (ON_PROCESS_EXIT)
- AppDomain::OnUnhandledException (ON_UNHANDLED_EXCEPTION)
- RunManagedStartup (MANAGED_STARTUP)
- RunMainInternal async helpers (HANDLE_ASYNC_ENTRYPOINT, TARGET_BROWSER)
- InvokeUtil::CreateClassLoadExcept (ReflectionTypeLoadException ctor)
- InvokeUtil::CreateTargetExcept (TargetInvocationException ctor)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Comment threadsrc/coreclr/vm/invokeutil.cpp Outdated
…-param and managed GetDefinedTypes() throws ReflectionTypeLoadException. Deleted reateClassLoadExcept + UCO wrapper + metasig as a result.
Adjusted OnUnhandledException in AppContext.CoreCLR.cs to use a bare catch based on feedback.
CopilotAI review requested due to automatic review settings February 25, 2026 16:49

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR converts priority 3 MethodDescCallSite/CallDescrWorker calls to more efficient UnmanagedCallersOnly reverse P/Invoke calls, following the established pattern from PR #124834. The conversions target application entry points and process lifecycle events in CoreCLR.

Changes:

  • Adds [UnmanagedCallersOnly] wrappers in managed code with Exception* out-parameters for exception propagation
  • Replaces native MethodDescCallSite calls with UnmanagedCallersOnlyCaller::InvokeThrowing template class
  • Refactors ReflectionTypeLoadException creation from native to managed code via QCall pattern

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.Browser.csAdds UCO wrapper for HandleAsyncEntryPoint to handle async Main entry points on Browser target
src/coreclr/System.Private.CoreLib/src/System/StartupHookProvider.CoreCLR.csAdds UCO wrapper for ManagedStartup with exception handling
src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.csAdds UCO wrapper for CreateTargetInvocationException
src/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.csNew file with UCO wrappers for OnProcessExit and OnUnhandledException
src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.csUpdates GetTypes QCall to return exceptions array for managed-side exception construction
src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csprojAdds new AppContext.CoreCLR.cs file to build
src/coreclr/vm/metasig.hAdds new metasig definitions for UCO method signatures
src/coreclr/vm/corelib.hUpdates DEFINE_METHOD entries to reference new UCO signatures
src/coreclr/vm/appdomain.cppReplaces MethodDescCallSite with UnmanagedCallersOnlyCaller for process lifecycle events
src/coreclr/vm/assembly.cppReplaces MethodDescCallSite with UnmanagedCallersOnlyCaller for startup hooks and async entry points
src/coreclr/vm/invokeutil.hRemoves obsolete CreateClassLoadExcept declaration
src/coreclr/vm/invokeutil.cppRemoves CreateClassLoadExcept implementation; converts CreateTargetExcept to use UCO pattern
src/coreclr/vm/commodule.hAdds retExceptions parameter to RuntimeModule_GetTypes QCall signature
src/coreclr/vm/commodule.cppReturns exceptions array via out-parameter instead of throwing from native code
src/coreclr/vm/exceptionhandlingqcalls.hFormatting fix - adds blank line at end of file

CopilotAI review requested due to automatic review settings February 25, 2026 18:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/coreclr/vm/commodule.cpp:766

  • RuntimeModule_GetTypes no longer throws inside the QCall when type loading fails, but the loop still doesn’t advance curPos on failure. With retExceptions.Set(...) replacing the throw, execution now continues and will hit _ASSERTE(curPos == dwNumTypeDefs) when any type load fails. Adjust the loop to keep curPos in sync with dwNumTypeDefs (e.g., advance and leave a null slot for failed loads, or remove/replace the assertion and ensure the returned Types array matches the intended semantics).
 // Return exceptions to managed side for throwing
if (cXcept > 0) {
gc.xceptRet = (PTRARRAYREF) AllocateObjectArray(cXcept,g_pExceptionClass);
for (DWORD i=0;i<cXcept;i++) {
gc.xceptRet->SetAt(i, gc.xcept->GetAt(i));
}
retExceptions.Set(gc.xceptRet);
}
// We should have filled the array exactly.
_ASSERTE(curPos == dwNumTypeDefs);

Comment threadsrc/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs Outdated
Comment threadsrc/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs Outdated
Comment threadsrc/coreclr/vm/invokeutil.cpp Outdated
Comment threadsrc/coreclr/vm/invokeutil.cpp
@jkotas

Copy link
Copy Markdown
Member

Test failure

ASSERT FAILED
Expression: curPos == dwNumTypeDefs
Location: /__w/1/s/src/coreclr/vm/commodule.cpp:765
Function: RuntimeModule_GetTypes
Process: 84956

Comment threadsrc/coreclr/vm/commodule.cpp
@jkotas

Copy link
Copy Markdown
Member

The wasm temporary callhelpers needs to be regenerated as part of these PRs: https://github.com/dotnet/runtime/blob/main/docs/workflow/wasm-documentation.md#running-coreclr-callhelpers-generator

CopilotAI review requested due to automatic review settings March 2, 2026 16:40

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/assembly.cpp
CopilotAI review requested due to automatic review settings March 5, 2026 15:57

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.


You can also share your feedback on Copilot code review. Take the survey.

Comment threadsrc/coreclr/vm/corelib.h
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@steveisok@jkotas@pavelsavara@radekdoulik@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Convert priority 3 MethodDescCallSite calls to UnmanagedCallersOnly - #124854

Merged
steveisok merged 24 commits into
dotnet:mainfrom
steveisok:uco-excep-p3
Mar 6, 2026
Merged

Convert priority 3 MethodDescCallSite calls to UnmanagedCallersOnly#124854
steveisok merged 24 commits into
dotnet:mainfrom
steveisok:uco-excep-p3

Conversation

@steveisok

Copy link
Copy Markdown
Member

First set of priority 3 conversions from #123864 — replace MethodDescCallSite/CallDescrWorker calls with UnmanagedCallersOnly reverse P/Invoke calls.

Converted call sites

FileCall siteMethod
appdomain.cppAppDomain::RaiseExitProcessEventON_PROCESS_EXIT
appdomain.cppAppDomain::OnUnhandledExceptionON_UNHANDLED_EXCEPTION
assembly.cppRunManagedStartupMANAGED_STARTUP
assembly.cppRunMainInternal (TARGET_BROWSER)HANDLE_ASYNC_ENTRYPOINT
invokeutil.cppInvokeUtil::CreateClassLoadExceptReflectionTypeLoadException ctor
invokeutil.cppInvokeUtil::CreateTargetExceptTargetInvocationException ctor

Remaining priority 3 items (follow ups)

  • Main entry point in RunMainInternal (dynamic MethodDesc)
  • CustomAttribute_CreateCustomAttributeInstance (dynamic ctor, already a QCall)
  • CorHost2::ExecuteAssembly (dynamic method lookup)
  • FuncEvalWrapper/DoNormalFuncEval (debugger func-eval)

Pattern

Follows the same conversion pattern as #124834 (priority 2). Each conversion adds an [UnmanagedCallersOnly] managed wrapper with an Exception* out-parameter and replaces the native MethodDescCallSite + ARG_SLOT with
UnmanagedCallersOnlyCaller::InvokeThrowing.

Replace MethodDescCallSite/CallDescrWorker calls with more efficient
UnmanagedCallersOnly reverse P/Invoke calls for priority 3 items from
dotnet#123864.
Converted call sites:
- AppDomain::RaiseExitProcessEvent (ON_PROCESS_EXIT)
- AppDomain::OnUnhandledException (ON_UNHANDLED_EXCEPTION)
- RunManagedStartup (MANAGED_STARTUP)
- RunMainInternal async helpers (HANDLE_ASYNC_ENTRYPOINT, TARGET_BROWSER)
- InvokeUtil::CreateClassLoadExcept (ReflectionTypeLoadException ctor)
- InvokeUtil::CreateTargetExcept (TargetInvocationException ctor)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Comment threadsrc/coreclr/vm/invokeutil.cpp Outdated
…-param and managed GetDefinedTypes() throws ReflectionTypeLoadException. Deleted reateClassLoadExcept + UCO wrapper + metasig as a result.
Adjusted OnUnhandledException in AppContext.CoreCLR.cs to use a bare catch based on feedback.
CopilotAI review requested due to automatic review settings February 25, 2026 16:49

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR converts priority 3 MethodDescCallSite/CallDescrWorker calls to more efficient UnmanagedCallersOnly reverse P/Invoke calls, following the established pattern from PR #124834. The conversions target application entry points and process lifecycle events in CoreCLR.

Changes:

  • Adds [UnmanagedCallersOnly] wrappers in managed code with Exception* out-parameters for exception propagation
  • Replaces native MethodDescCallSite calls with UnmanagedCallersOnlyCaller::InvokeThrowing template class
  • Refactors ReflectionTypeLoadException creation from native to managed code via QCall pattern

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.Browser.csAdds UCO wrapper for HandleAsyncEntryPoint to handle async Main entry points on Browser target
src/coreclr/System.Private.CoreLib/src/System/StartupHookProvider.CoreCLR.csAdds UCO wrapper for ManagedStartup with exception handling
src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.csAdds UCO wrapper for CreateTargetInvocationException
src/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.csNew file with UCO wrappers for OnProcessExit and OnUnhandledException
src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.csUpdates GetTypes QCall to return exceptions array for managed-side exception construction
src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csprojAdds new AppContext.CoreCLR.cs file to build
src/coreclr/vm/metasig.hAdds new metasig definitions for UCO method signatures
src/coreclr/vm/corelib.hUpdates DEFINE_METHOD entries to reference new UCO signatures
src/coreclr/vm/appdomain.cppReplaces MethodDescCallSite with UnmanagedCallersOnlyCaller for process lifecycle events
src/coreclr/vm/assembly.cppReplaces MethodDescCallSite with UnmanagedCallersOnlyCaller for startup hooks and async entry points
src/coreclr/vm/invokeutil.hRemoves obsolete CreateClassLoadExcept declaration
src/coreclr/vm/invokeutil.cppRemoves CreateClassLoadExcept implementation; converts CreateTargetExcept to use UCO pattern
src/coreclr/vm/commodule.hAdds retExceptions parameter to RuntimeModule_GetTypes QCall signature
src/coreclr/vm/commodule.cppReturns exceptions array via out-parameter instead of throwing from native code
src/coreclr/vm/exceptionhandlingqcalls.hFormatting fix - adds blank line at end of file

CopilotAI review requested due to automatic review settings February 25, 2026 18:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/coreclr/vm/commodule.cpp:766

  • RuntimeModule_GetTypes no longer throws inside the QCall when type loading fails, but the loop still doesn’t advance curPos on failure. With retExceptions.Set(...) replacing the throw, execution now continues and will hit _ASSERTE(curPos == dwNumTypeDefs) when any type load fails. Adjust the loop to keep curPos in sync with dwNumTypeDefs (e.g., advance and leave a null slot for failed loads, or remove/replace the assertion and ensure the returned Types array matches the intended semantics).
 // Return exceptions to managed side for throwing
if (cXcept > 0) {
gc.xceptRet = (PTRARRAYREF) AllocateObjectArray(cXcept,g_pExceptionClass);
for (DWORD i=0;i<cXcept;i++) {
gc.xceptRet->SetAt(i, gc.xcept->GetAt(i));
}
retExceptions.Set(gc.xceptRet);
}
// We should have filled the array exactly.
_ASSERTE(curPos == dwNumTypeDefs);

Comment threadsrc/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs Outdated
Comment threadsrc/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs Outdated
Comment threadsrc/coreclr/vm/invokeutil.cpp Outdated
Comment threadsrc/coreclr/vm/invokeutil.cpp
@jkotas

Copy link
Copy Markdown
Member

Test failure

ASSERT FAILED
Expression: curPos == dwNumTypeDefs
Location: /__w/1/s/src/coreclr/vm/commodule.cpp:765
Function: RuntimeModule_GetTypes
Process: 84956

Comment threadsrc/coreclr/vm/commodule.cpp
@jkotas

Copy link
Copy Markdown
Member

The wasm temporary callhelpers needs to be regenerated as part of these PRs: https://github.com/dotnet/runtime/blob/main/docs/workflow/wasm-documentation.md#running-coreclr-callhelpers-generator

CopilotAI review requested due to automatic review settings March 2, 2026 16:40

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/assembly.cpp
CopilotAI review requested due to automatic review settings March 5, 2026 15:57

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.


You can also share your feedback on Copilot code review. Take the survey.

Comment threadsrc/coreclr/vm/corelib.h
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@steveisok@jkotas@pavelsavara@radekdoulik@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Convert priority 3 MethodDescCallSite calls to UnmanagedCallersOnly - #124854

Merged
steveisok merged 24 commits into
dotnet:mainfrom
steveisok:uco-excep-p3
Mar 6, 2026
Merged

Convert priority 3 MethodDescCallSite calls to UnmanagedCallersOnly#124854
steveisok merged 24 commits into
dotnet:mainfrom
steveisok:uco-excep-p3

Conversation

@steveisok

Copy link
Copy Markdown
Member

First set of priority 3 conversions from #123864 — replace MethodDescCallSite/CallDescrWorker calls with UnmanagedCallersOnly reverse P/Invoke calls.

Converted call sites

FileCall siteMethod
appdomain.cppAppDomain::RaiseExitProcessEventON_PROCESS_EXIT
appdomain.cppAppDomain::OnUnhandledExceptionON_UNHANDLED_EXCEPTION
assembly.cppRunManagedStartupMANAGED_STARTUP
assembly.cppRunMainInternal (TARGET_BROWSER)HANDLE_ASYNC_ENTRYPOINT
invokeutil.cppInvokeUtil::CreateClassLoadExceptReflectionTypeLoadException ctor
invokeutil.cppInvokeUtil::CreateTargetExceptTargetInvocationException ctor

Remaining priority 3 items (follow ups)

  • Main entry point in RunMainInternal (dynamic MethodDesc)
  • CustomAttribute_CreateCustomAttributeInstance (dynamic ctor, already a QCall)
  • CorHost2::ExecuteAssembly (dynamic method lookup)
  • FuncEvalWrapper/DoNormalFuncEval (debugger func-eval)

Pattern

Follows the same conversion pattern as #124834 (priority 2). Each conversion adds an [UnmanagedCallersOnly] managed wrapper with an Exception* out-parameter and replaces the native MethodDescCallSite + ARG_SLOT with
UnmanagedCallersOnlyCaller::InvokeThrowing.

Replace MethodDescCallSite/CallDescrWorker calls with more efficient
UnmanagedCallersOnly reverse P/Invoke calls for priority 3 items from
dotnet#123864.
Converted call sites:
- AppDomain::RaiseExitProcessEvent (ON_PROCESS_EXIT)
- AppDomain::OnUnhandledException (ON_UNHANDLED_EXCEPTION)
- RunManagedStartup (MANAGED_STARTUP)
- RunMainInternal async helpers (HANDLE_ASYNC_ENTRYPOINT, TARGET_BROWSER)
- InvokeUtil::CreateClassLoadExcept (ReflectionTypeLoadException ctor)
- InvokeUtil::CreateTargetExcept (TargetInvocationException ctor)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Comment threadsrc/coreclr/vm/invokeutil.cpp Outdated
…-param and managed GetDefinedTypes() throws ReflectionTypeLoadException. Deleted reateClassLoadExcept + UCO wrapper + metasig as a result.
Adjusted OnUnhandledException in AppContext.CoreCLR.cs to use a bare catch based on feedback.
CopilotAI review requested due to automatic review settings February 25, 2026 16:49

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR converts priority 3 MethodDescCallSite/CallDescrWorker calls to more efficient UnmanagedCallersOnly reverse P/Invoke calls, following the established pattern from PR #124834. The conversions target application entry points and process lifecycle events in CoreCLR.

Changes:

  • Adds [UnmanagedCallersOnly] wrappers in managed code with Exception* out-parameters for exception propagation
  • Replaces native MethodDescCallSite calls with UnmanagedCallersOnlyCaller::InvokeThrowing template class
  • Refactors ReflectionTypeLoadException creation from native to managed code via QCall pattern

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.Browser.csAdds UCO wrapper for HandleAsyncEntryPoint to handle async Main entry points on Browser target
src/coreclr/System.Private.CoreLib/src/System/StartupHookProvider.CoreCLR.csAdds UCO wrapper for ManagedStartup with exception handling
src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.csAdds UCO wrapper for CreateTargetInvocationException
src/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.csNew file with UCO wrappers for OnProcessExit and OnUnhandledException
src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.csUpdates GetTypes QCall to return exceptions array for managed-side exception construction
src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csprojAdds new AppContext.CoreCLR.cs file to build
src/coreclr/vm/metasig.hAdds new metasig definitions for UCO method signatures
src/coreclr/vm/corelib.hUpdates DEFINE_METHOD entries to reference new UCO signatures
src/coreclr/vm/appdomain.cppReplaces MethodDescCallSite with UnmanagedCallersOnlyCaller for process lifecycle events
src/coreclr/vm/assembly.cppReplaces MethodDescCallSite with UnmanagedCallersOnlyCaller for startup hooks and async entry points
src/coreclr/vm/invokeutil.hRemoves obsolete CreateClassLoadExcept declaration
src/coreclr/vm/invokeutil.cppRemoves CreateClassLoadExcept implementation; converts CreateTargetExcept to use UCO pattern
src/coreclr/vm/commodule.hAdds retExceptions parameter to RuntimeModule_GetTypes QCall signature
src/coreclr/vm/commodule.cppReturns exceptions array via out-parameter instead of throwing from native code
src/coreclr/vm/exceptionhandlingqcalls.hFormatting fix - adds blank line at end of file

CopilotAI review requested due to automatic review settings February 25, 2026 18:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/coreclr/vm/commodule.cpp:766

  • RuntimeModule_GetTypes no longer throws inside the QCall when type loading fails, but the loop still doesn’t advance curPos on failure. With retExceptions.Set(...) replacing the throw, execution now continues and will hit _ASSERTE(curPos == dwNumTypeDefs) when any type load fails. Adjust the loop to keep curPos in sync with dwNumTypeDefs (e.g., advance and leave a null slot for failed loads, or remove/replace the assertion and ensure the returned Types array matches the intended semantics).
 // Return exceptions to managed side for throwing
if (cXcept > 0) {
gc.xceptRet = (PTRARRAYREF) AllocateObjectArray(cXcept,g_pExceptionClass);
for (DWORD i=0;i<cXcept;i++) {
gc.xceptRet->SetAt(i, gc.xcept->GetAt(i));
}
retExceptions.Set(gc.xceptRet);
}
// We should have filled the array exactly.
_ASSERTE(curPos == dwNumTypeDefs);

Comment threadsrc/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs Outdated
Comment threadsrc/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs Outdated
Comment threadsrc/coreclr/vm/invokeutil.cpp Outdated
Comment threadsrc/coreclr/vm/invokeutil.cpp
@jkotas

Copy link
Copy Markdown
Member

Test failure

ASSERT FAILED
Expression: curPos == dwNumTypeDefs
Location: /__w/1/s/src/coreclr/vm/commodule.cpp:765
Function: RuntimeModule_GetTypes
Process: 84956

Comment threadsrc/coreclr/vm/commodule.cpp
@jkotas

Copy link
Copy Markdown
Member

The wasm temporary callhelpers needs to be regenerated as part of these PRs: https://github.com/dotnet/runtime/blob/main/docs/workflow/wasm-documentation.md#running-coreclr-callhelpers-generator

CopilotAI review requested due to automatic review settings March 2, 2026 16:40

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/assembly.cpp
CopilotAI review requested due to automatic review settings March 5, 2026 15:57

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.


You can also share your feedback on Copilot code review. Take the survey.

Comment threadsrc/coreclr/vm/corelib.h
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@steveisok@jkotas@pavelsavara@radekdoulik@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Convert priority 3 MethodDescCallSite calls to UnmanagedCallersOnly - #124854

Merged
steveisok merged 24 commits into
dotnet:mainfrom
steveisok:uco-excep-p3
Mar 6, 2026
Merged

Convert priority 3 MethodDescCallSite calls to UnmanagedCallersOnly#124854
steveisok merged 24 commits into
dotnet:mainfrom
steveisok:uco-excep-p3

Conversation

@steveisok

Copy link
Copy Markdown
Member

First set of priority 3 conversions from #123864 — replace MethodDescCallSite/CallDescrWorker calls with UnmanagedCallersOnly reverse P/Invoke calls.

Converted call sites

FileCall siteMethod
appdomain.cppAppDomain::RaiseExitProcessEventON_PROCESS_EXIT
appdomain.cppAppDomain::OnUnhandledExceptionON_UNHANDLED_EXCEPTION
assembly.cppRunManagedStartupMANAGED_STARTUP
assembly.cppRunMainInternal (TARGET_BROWSER)HANDLE_ASYNC_ENTRYPOINT
invokeutil.cppInvokeUtil::CreateClassLoadExceptReflectionTypeLoadException ctor
invokeutil.cppInvokeUtil::CreateTargetExceptTargetInvocationException ctor

Remaining priority 3 items (follow ups)

  • Main entry point in RunMainInternal (dynamic MethodDesc)
  • CustomAttribute_CreateCustomAttributeInstance (dynamic ctor, already a QCall)
  • CorHost2::ExecuteAssembly (dynamic method lookup)
  • FuncEvalWrapper/DoNormalFuncEval (debugger func-eval)

Pattern

Follows the same conversion pattern as #124834 (priority 2). Each conversion adds an [UnmanagedCallersOnly] managed wrapper with an Exception* out-parameter and replaces the native MethodDescCallSite + ARG_SLOT with
UnmanagedCallersOnlyCaller::InvokeThrowing.

Replace MethodDescCallSite/CallDescrWorker calls with more efficient
UnmanagedCallersOnly reverse P/Invoke calls for priority 3 items from
dotnet#123864.
Converted call sites:
- AppDomain::RaiseExitProcessEvent (ON_PROCESS_EXIT)
- AppDomain::OnUnhandledException (ON_UNHANDLED_EXCEPTION)
- RunManagedStartup (MANAGED_STARTUP)
- RunMainInternal async helpers (HANDLE_ASYNC_ENTRYPOINT, TARGET_BROWSER)
- InvokeUtil::CreateClassLoadExcept (ReflectionTypeLoadException ctor)
- InvokeUtil::CreateTargetExcept (TargetInvocationException ctor)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Comment threadsrc/coreclr/vm/invokeutil.cpp Outdated
…-param and managed GetDefinedTypes() throws ReflectionTypeLoadException. Deleted reateClassLoadExcept + UCO wrapper + metasig as a result.
Adjusted OnUnhandledException in AppContext.CoreCLR.cs to use a bare catch based on feedback.
CopilotAI review requested due to automatic review settings February 25, 2026 16:49

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR converts priority 3 MethodDescCallSite/CallDescrWorker calls to more efficient UnmanagedCallersOnly reverse P/Invoke calls, following the established pattern from PR #124834. The conversions target application entry points and process lifecycle events in CoreCLR.

Changes:

  • Adds [UnmanagedCallersOnly] wrappers in managed code with Exception* out-parameters for exception propagation
  • Replaces native MethodDescCallSite calls with UnmanagedCallersOnlyCaller::InvokeThrowing template class
  • Refactors ReflectionTypeLoadException creation from native to managed code via QCall pattern

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.

Show a summary per file
FileDescription
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.Browser.csAdds UCO wrapper for HandleAsyncEntryPoint to handle async Main entry points on Browser target
src/coreclr/System.Private.CoreLib/src/System/StartupHookProvider.CoreCLR.csAdds UCO wrapper for ManagedStartup with exception handling
src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.csAdds UCO wrapper for CreateTargetInvocationException
src/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.csNew file with UCO wrappers for OnProcessExit and OnUnhandledException
src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.csUpdates GetTypes QCall to return exceptions array for managed-side exception construction
src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csprojAdds new AppContext.CoreCLR.cs file to build
src/coreclr/vm/metasig.hAdds new metasig definitions for UCO method signatures
src/coreclr/vm/corelib.hUpdates DEFINE_METHOD entries to reference new UCO signatures
src/coreclr/vm/appdomain.cppReplaces MethodDescCallSite with UnmanagedCallersOnlyCaller for process lifecycle events
src/coreclr/vm/assembly.cppReplaces MethodDescCallSite with UnmanagedCallersOnlyCaller for startup hooks and async entry points
src/coreclr/vm/invokeutil.hRemoves obsolete CreateClassLoadExcept declaration
src/coreclr/vm/invokeutil.cppRemoves CreateClassLoadExcept implementation; converts CreateTargetExcept to use UCO pattern
src/coreclr/vm/commodule.hAdds retExceptions parameter to RuntimeModule_GetTypes QCall signature
src/coreclr/vm/commodule.cppReturns exceptions array via out-parameter instead of throwing from native code
src/coreclr/vm/exceptionhandlingqcalls.hFormatting fix - adds blank line at end of file

CopilotAI review requested due to automatic review settings February 25, 2026 18:50

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

src/coreclr/vm/commodule.cpp:766

  • RuntimeModule_GetTypes no longer throws inside the QCall when type loading fails, but the loop still doesn’t advance curPos on failure. With retExceptions.Set(...) replacing the throw, execution now continues and will hit _ASSERTE(curPos == dwNumTypeDefs) when any type load fails. Adjust the loop to keep curPos in sync with dwNumTypeDefs (e.g., advance and leave a null slot for failed loads, or remove/replace the assertion and ensure the returned Types array matches the intended semantics).
 // Return exceptions to managed side for throwing
if (cXcept > 0) {
gc.xceptRet = (PTRARRAYREF) AllocateObjectArray(cXcept,g_pExceptionClass);
for (DWORD i=0;i<cXcept;i++) {
gc.xceptRet->SetAt(i, gc.xcept->GetAt(i));
}
retExceptions.Set(gc.xceptRet);
}
// We should have filled the array exactly.
_ASSERTE(curPos == dwNumTypeDefs);

Comment threadsrc/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs Outdated
Comment threadsrc/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs Outdated
Comment threadsrc/coreclr/vm/invokeutil.cpp Outdated
Comment threadsrc/coreclr/vm/invokeutil.cpp
@jkotas

Copy link
Copy Markdown
Member

Test failure

ASSERT FAILED
Expression: curPos == dwNumTypeDefs
Location: /__w/1/s/src/coreclr/vm/commodule.cpp:765
Function: RuntimeModule_GetTypes
Process: 84956

Comment threadsrc/coreclr/vm/commodule.cpp
@jkotas

Copy link
Copy Markdown
Member

The wasm temporary callhelpers needs to be regenerated as part of these PRs: https://github.com/dotnet/runtime/blob/main/docs/workflow/wasm-documentation.md#running-coreclr-callhelpers-generator

CopilotAI review requested due to automatic review settings March 2, 2026 16:40

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Comment threadsrc/coreclr/vm/assembly.cpp
CopilotAI review requested due to automatic review settings March 5, 2026 15:57

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 1 comment.


You can also share your feedback on Copilot code review. Take the survey.

Comment threadsrc/coreclr/vm/corelib.h
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

@steveisok@jkotas@pavelsavara@radekdoulik@AaronRobinsonMSFT