Route QCall exceptions through marshalling - #132420
Conversation
|
Tagging subscribers to this area: @agocke |
There was a problem hiding this comment.
Pull request overview
This PR changes CoreCLR QCall exception propagation by routing exceptions thrown inside BEGIN_QCALL/END_QCALL through an out QCallException status value that is custom-marshalled back to managed code. The native side captures throwables onto the managed Thread, and the managed marshaller rethrows during unmarshalling, while leaving non-BEGIN_QCALL QCalls on the prior behavior.
Changes:
- Introduce
QCallException+QCallExceptionMarshallerand update managed QCall signatures to include anout QCallExceptionforBEGIN_QCALL-based QCalls. - Update native QCall entrypoints and exception macros to capture exceptions instead of dispatching/rethrowing directly across the boundary.
- Add the per-thread storage needed to temporarily root the captured throwable and rethrow it from managed unmarshalling.
Reviewed changes
Copilot reviewed 170 out of 170 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/libraries/System.Private.CoreLib/src/System/Threading/Wasi/WasiFinalizerScheduler.cs | Add conditional out QCallException to WASI finalizer QCalls. |
| src/libraries/System.Private.CoreLib/src/System/Threading/WaitHandle.Windows.cs | Pass conditional out _ to updated reentrant wait QCall. |
| src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs | Update CurrentOSThreadId QCall invocation to include conditional out _. |
| src/libraries/System.Private.CoreLib/src/System/Threading/Lock.cs | Use updated Environment.GetProcessorCount signature under CORECLR. |
| src/libraries/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.cs | Thread out QCallException through multiple tracing/ALC QCalls. |
| src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TypeMapLazyDictionary.cs | Add out QCallException to QCalls used by type map cache population/lookups. |
| src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveC/ObjectiveCMarshal.cs | Pass out _ to updated ObjC marshal QCalls. |
| src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.NoCom.cs | Extend internal signature with conditional out _ under CORECLR. |
| src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs | Call updated RegisterIsRootedCallback under CORECLR. |
| src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs | Update tracing QCall invocations to include out _. |
| src/libraries/System.Private.CoreLib/src/System/Environment.cs | Update ProcessorCount initialization to use CORECLR QCall signature. |
| src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/XplatEventLogger.cs | Add out QCallException plumbing to xplat EventSource QCalls. |
| src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeEventProvider.cs | Add conditional out _ to EventPipeInternal QCalls. |
| src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeEventDispatcher.Threads.cs | Add conditional out _ to EventPipe session wait/disable QCalls. |
| src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipeEventDispatcher.cs | Add conditional out _ to EventPipe dispatcher QCalls. |
| src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventPipe.cs | Add conditional out _ to EventPipe enable QCall. |
| src/libraries/System.Private.CoreLib/src/System/AppContext.cs | Add conditional out _ to host property QCall path. |
| src/coreclr/vm/weakreferencenative.h | Add QCallException* to COM weak ref QCall signatures. |
| src/coreclr/vm/weakreferencenative.cpp | Add QCallException* parameter to COM weak ref QCall implementations. |
| src/coreclr/vm/wasm/entrypoints.h | Add QCallException* to WASI finalizer exported entrypoints. |
| src/coreclr/vm/versionresilienthashcode.h | Add QCallException* to version-resilient hash QCall signature. |
| src/coreclr/vm/versionresilienthashcode.cpp | Add QCallException* to version-resilient hash QCall implementation. |
| src/coreclr/vm/varargsnative.h | Add QCallException* to varargs iterator QCall signatures. |
| src/coreclr/vm/varargsnative.cpp | Add QCallException* to varargs iterator QCall implementations. |
| src/coreclr/vm/unsafeaccessors.cpp | Add QCallException* to unsafe accessor resolver QCall. |
| src/coreclr/vm/tailcallhelp.h | Add QCallException* to tailcall arg buffer allocation QCall. |
| src/coreclr/vm/tailcallhelp.cpp | Add QCallException* to tailcall arg buffer allocation QCall implementation. |
| src/coreclr/vm/stubhelpers.h | Add QCallException* to multiple interop/stub helper QCall signatures. |
| src/coreclr/vm/stackwalk.h | Add QCallException* to AppendExceptionStackFrame QCall signature. |
| src/coreclr/vm/reflectioninvocation.h | Add QCallException* to reflection invocation QCall signatures. |
| src/coreclr/vm/qcall.h | Update QCall guidance/comments and route BEGIN/END macros to capture dispatcher. |
| src/coreclr/vm/qcall.cpp | Add QCallException::SetThrowable implementation and thread rooting logic. |
| src/coreclr/vm/olevariant.h | Add QCallException* to VARIANT record conversion QCall signature. |
| src/coreclr/vm/olevariant.cpp | Add QCallException* to VARIANT record conversion QCall implementation. |
| src/coreclr/vm/object.h | Add m_QCallException field + setter on ThreadBaseObject. |
| src/coreclr/vm/nativelibrarynative.h | Add QCallException* to NativeLibrary load-by-name QCall signature. |
| src/coreclr/vm/nativelibrarynative.cpp | Add QCallException* to NativeLibrary load-by-name QCall implementation. |
| src/coreclr/vm/nativeeventsource.h | Add QCallException* to EventSource/perf tracing QCall signatures. |
| src/coreclr/vm/multicorejit.h | Add QCallException* to MultiCoreJIT QCall signatures. |
| src/coreclr/vm/multicorejit.cpp | Add QCallException* to MultiCoreJIT QCall implementations. |
| src/coreclr/vm/mlinfo.cpp | Add QCallException* to StubHelpers_CreateCustomMarshaler QCall implementation. |
| src/coreclr/vm/method.hpp | Add QCallException* to unsafe accessor resolver declaration. |
| src/coreclr/vm/managedmdimport.hpp | Add QCallException* to metadata enum QCall signature. |
| src/coreclr/vm/managedmdimport.cpp | Add QCallException* to metadata enum QCall implementation. |
| src/coreclr/vm/loaderallocator.hpp | Add QCallException* to loader allocator destroy QCall signature. |
| src/coreclr/vm/loaderallocator.cpp | Add QCallException* to loader allocator destroy QCall implementation. |
| src/coreclr/vm/JitQCallHelpers.h | Add QCallException* to JIT helper QCall signatures. |
| src/coreclr/vm/jithelpers.cpp | Add QCallException* to JIT helper QCalls and adjust handler installation in rare paths. |
| src/coreclr/vm/interoplibinterface.h | Add QCallException* to ObjC/Java marshal QCall signatures. |
| src/coreclr/vm/interoplibinterface_objc.cpp | Add QCallException* to ObjC marshal QCall implementations. |
| src/coreclr/vm/interoplibinterface_java.cpp | Add QCallException* to Java marshal QCall implementations. |
| src/coreclr/vm/interoplibinterface_comwrappers.h | Add QCallException* to ComWrappers QCall signatures. |
| src/coreclr/vm/interoplibinterface_comwrappers.cpp | Add QCallException* to ComWrappers QCall implementations. |
| src/coreclr/vm/ilmarshalers.h | Add QCallException* to safe array marshaler QCall signatures. |
| src/coreclr/vm/ilmarshalers.cpp | Add QCallException* to safe array marshaler QCall implementations. |
| src/coreclr/vm/finalizerthread.cpp | Add QCallException* to WASI finalizer QCall implementations. |
| src/coreclr/vm/exceptmacros.h | Introduce QCallException native struct and capture-dispatcher exception macros. |
| src/coreclr/vm/exceptionhandlingqcalls.h | Add QCallException* to exception-handling-related QCall signatures. |
| src/coreclr/vm/exceptionhandling.cpp | Add QCallException* to exception-handling-related QCall implementations. |
| src/coreclr/vm/excep.cpp | Add QCallException* to message QCalls and introduce QCall-specific unwind helper. |
| src/coreclr/vm/eventpipeinternal.h | Add QCallException* to EventPipeInternal QCall signatures. |
| src/coreclr/vm/eventpipeinternal.cpp | Add QCallException* to EventPipeInternal QCall implementations. |
| src/coreclr/vm/debugdebugger.h | Add QCallException* to debugger/stacktrace QCall signatures. |
| src/coreclr/vm/debugdebugger.cpp | Add QCallException* to debugger/stacktrace QCall implementations. |
| src/coreclr/vm/customattribute.h | Add QCallException* to custom attribute QCall signatures. |
| src/coreclr/vm/customattribute.cpp | Add QCallException* to custom attribute QCall implementations. |
| src/coreclr/vm/corelib.h | Add corelib field mapping for new thread _qcallException field. |
| src/coreclr/vm/coreassemblyspec.cpp | Add QCallException* to assembly spec initialization QCall signature. |
| src/coreclr/vm/comsynchronizable.h | Add QCallException* to thread/lock-related QCall signatures. |
| src/coreclr/vm/comsynchronizable.cpp | Add QCallException* to thread/lock-related QCall implementations. |
| src/coreclr/vm/commodule.h | Add QCallException* to Reflection.Emit module builder QCall signatures. |
| src/coreclr/vm/commodule.cpp | Add QCallException* to Reflection.Emit module builder QCall implementations. |
| src/coreclr/vm/comdependenthandle.h | Add QCallException* to dependent handle QCall signatures. |
| src/coreclr/vm/comdependenthandle.cpp | Add QCallException* to dependent handle QCall implementations. |
| src/coreclr/vm/comdelegate.h | Add QCallException* to delegate-related QCall signatures. |
| src/coreclr/vm/comdelegate.cpp | Add QCallException* to delegate-related QCall implementations. |
| src/coreclr/vm/clrconfignative.h | Add QCallException* to CLR config QCall signature. |
| src/coreclr/vm/clrconfignative.cpp | Add QCallException* to CLR config QCall implementation. |
| src/coreclr/vm/arraynative.h | Add QCallException* to array creation/ctor QCall signatures. |
| src/coreclr/vm/arraynative.cpp | Add QCallException* to array creation/ctor QCall implementations. |
| src/coreclr/vm/appdomainnative.hpp | Add QCallException* to AppDomain/AppContext/string intern QCall signatures. |
| src/coreclr/vm/appdomainnative.cpp | Add QCallException* to AppDomain/AppContext/string intern QCall implementations. |
| src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj | Include new QCallException.cs in CoreCLR CoreLib build. |
| src/coreclr/System.Private.CoreLib/src/System/Variant.cs | Add out QCallException to COM VARIANT-related QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/ValueType.cs | Add out QCallException to ValueType helper QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/TypeLoadException.CoreCLR.cs | Add out QCallException to message-formatting QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Threading/ObjectHeader.CoreCLR.cs | Add out QCallException to lock-object QCall. |
| src/coreclr/System.Private.CoreLib/src/System/String.CoreCLR.cs | Add out QCallException to string intern/is-interned QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CreateUninitializedCache.CoreCLR.cs | Add out QCallException to create-uninitialized info QCall. |
| src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs | Add out QCallException to multiple RuntimeType/reflection QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/RuntimeType.BoxCache.cs | Add out QCallException to boxing cache QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.CoreCLR.cs | Add out QCallException to wrapper-cache registration QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveCMarshal.CoreCLR.cs | Add out QCallException to ObjC marshal QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.CoreCLR.cs | Add out QCallException to NativeLibrary load QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/Java/JavaMarshal.CoreCLR.cs | Add out QCallException to Java marshal QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.CoreCLR.cs | Add out QCallException to GCHandle QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreCLR.cs | Add out QCallException to ComWrappers QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/ExceptionServices/InternalCalls.cs | Add out QCallException to EH-related QCall internal calls. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/DependentHandle.cs | Add out QCallException to dependent handle QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/ControlledExecution.CoreCLR.cs | Add out QCallException to ThreadNative_Abort QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/VirtualDispatchHelpers.cs | Add out QCallException to virtual dispatch resolver QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/StaticsHelpers.cs | Add out QCallException to thread statics QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/QCallException.cs | Introduce managed QCall exception status type + custom marshaller. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/InitHelpers.cs | Add out QCallException to init-class QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/GenericsHelpers.cs | Add out QCallException to generic handle worker QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastHelpers.cs | Add out QCallException to cast helper QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncHelpers.CoreCLR.cs | Add out QCallException to async continuation QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.CoreCLR.cs | Add out QCallException to unsafe accessor resolver QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs | Add out QCallException to module name/types QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs | Add out QCallException to custom attribute QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs | Add out QCallException to GetCurrentMethod QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Reflection/Metadata/MetadataUpdater.cs | Add out QCallException to metadata update QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/Reflection/Metadata/AssemblyExtensions.cs | Add out QCallException to raw metadata QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Reflection/MdImport.cs | Add out QCallException to metadata import enum QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Reflection/LoaderAllocator.cs | Add out QCallException to loader allocator destroy QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimePropertyBuilder.cs | Add out _ to Reflection.Emit QCall invocations. |
| src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeParameterBuilder.cs | Add out _ to Reflection.Emit QCall invocations. |
| src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.cs | Add out _ to Reflection.Emit QCall invocations. |
| src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeFieldBuilder.cs | Add out _ to Reflection.Emit QCall invocations. |
| src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeEventBuilder.cs | Add out _ to Reflection.Emit QCall invocations. |
| src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeAssemblyBuilder.cs | Add out QCallException to dynamic assembly creation QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.CoreCLR.cs | Add out _ to compile-method QCall invocation. |
| src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicILGenerator.cs | Add out _ to destroy handle QCall invocation. |
| src/coreclr/System.Private.CoreLib/src/System/Reflection/AssemblyName.CoreCLR.cs | Add out QCallException to assembly spec init QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Reflection/Assembly.CoreCLR.cs | Add out QCallException to assembly lookup QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/Object.CoreCLR.cs | Add out _ to clone allocation QCall invocation. |
| src/coreclr/System.Private.CoreLib/src/System/IO/Stream.CoreCLR.cs | Add out QCallException to overridden-check QCall. |
| src/coreclr/System.Private.CoreLib/src/System/IO/FileLoadException.CoreCLR.cs | Add out QCallException to file load message QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/Exception.CoreCLR.cs | Add out QCallException to exception-related QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/Environment.CoreCLR.cs | Add out QCallException to Environment QCalls (Exit/FailFast/GetProcessorCount). |
| src/coreclr/System.Private.CoreLib/src/System/Enum.CoreCLR.cs | Add out QCallException to enum values/names QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackTrace.CoreCLR.cs | Add out QCallException to stack trace frames QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Diagnostics/StackFrame.CoreCLR.cs | Add out QCallException to method-desc-from-IP QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Debugger.cs | Add out QCallException to debugger break/notification QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs | Add out QCallException to delegate binding/construct QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/ComAwareWeakReference.CoreCLR.cs | Add out QCallException to COM weak ref QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/CLRConfig.cs | Add out QCallException to CLR config QCall. |
| src/coreclr/System.Private.CoreLib/src/System/Array.CoreCLR.cs | Add out QCallException to array creation/ctor QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/ArgIterator.cs | Add out QCallException to varargs iterator QCalls. |
| src/coreclr/System.Private.CoreLib/src/System/AppContext.CoreCLR.cs | Add out QCallException to host property QCall. |
| src/coreclr/System.Private.CoreLib/src/Internal/VersionResilientHashCode.CoreCLR.cs | Add out QCallException to version-resilient hash QCall. |
| src/coreclr/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/ThrowHelpers.cs | Add out QCallException to throw-helper QCalls. |
| src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/StackFrameIterator.cs | Add conditional out _ to EH QCall internal calls. |
| src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/ExceptionHandling.cs | Add conditional out _ to EH QCall internal calls. |
|
|
||
| if (exceptionPending == 1) | ||
| { | ||
| Exception exception = _thread.GetAndClearQCallException(); |
| { \ | ||
| GCX_COOP(); \ | ||
| OBJECTREF throwable = ExInfo::CreateThrowable(ex.GetExceptionRecord(), FALSE); \ | ||
| qcallError->SetThrowable(throwable); \ | ||
| } \ |
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
| namespace System.Runtime.CompilerServices | ||
| { | ||
| [NativeMarshalling(typeof(QCallExceptionMarshaller))] | ||
| internal readonly struct QCallException |
There was a problem hiding this comment.
Naming nit: The name makes it look like an exception type per .NET naming guidelines, but it is not actually an exception type. Copilot suggests QCallExceptionStatus as a better name:
Yes. QCallException is misleading because the type is an out-only marshalling protocol/status value, not an exception object.
My preferred name would be:
internal readonly struct QCallExceptionStatusThis communicates that:
- it is associated with QCall exception propagation;
- it is a status/result value;
- it is not itself throwable or derived from
Exception.
Other reasonable alternatives:
| Name | Comments |
|---|---|
QCallExceptionStatus |
Best overall; explicit and reasonably concise. |
QCallExceptionPropagation |
Emphasizes that its purpose is transferring a pending exception across the boundary. A little abstract for a value type. |
QCallExceptionResult |
Good if the parameter is viewed as an invocation result, although “result” may imply the exception itself is returned. |
QCallThrowStatus |
Short and accurately describes the behavior, but “throw” may sound like an operation rather than a status. |
QCallErrorStatus |
Avoids calling it an exception, but loses the important distinction that it carries managed exceptions rather than ordinary error codes. |
QCallExceptionToken |
Suggests an opaque token, which is not quite accurate because the marshaller retrieves the exception from the managed thread. |
QCallExceptionCarrier |
Describes the mechanism, but sounds like it contains the exception, which the empty managed struct does not. |
I would also consider renaming the native pointer consistently:
QCallExceptionStatus* qcallExceptionStatusor, if using the shorter managed name:
QCallThrowStatus* qcallThrowStatusFor example:
[NativeMarshalling(typeof(QCallExceptionStatusMarshaller))]
internal readonly struct QCallExceptionStatus
{
}private static partial void SomeQCall(
...,
out QCallExceptionStatus exceptionStatus);The strongest alternative if you want to avoid Exception entirely is probably:
QCallThrowStatusHowever, I would favor QCallExceptionStatus because it preserves the semantic connection to the managed exception being propagated while making clear that the type itself is merely a status marker.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 97d405d-8e39-4e76-afe4-2f94b74ecfa2
| private static IntPtr AllocateReferenceTrackingHandle(object obj) | ||
| => AllocateReferenceTrackingHandle(ObjectHandleOnStack.Create(ref obj)); |
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 171 out of 171 changed files in this pull request and generated no new comments.
Suppressed comments (1)
src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/QCallException.cs:26
QCallExceptionMarshaller.FromUnmanagedonly treatsexceptionPending == 1as an exception. Since the native representation is anINT32flag, using a non-zero check (!= 0) is more robust against future expansion or accidental non-1 values, and avoids silently skipping exception propagation if the flag is ever set to another non-zero value.
Add managed forwarding overloads for helpers invoked by native IL stub generation so their CoreLib binder signatures remain stable after adding QCall exception parameters. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 97d405d-8e39-4e76-afe4-2f94b74ecfa2
Keep the CoreCLR QCall exception argument and Mono zero-argument call in separately formatted conditional branches so both CoreLib builds satisfy style validation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 97d405d-8e39-4e76-afe4-2f94b74ecfa2
Update browser and WASI interpreter-to-managed thunks for the QCall exception argument and refresh generated P/Invoke tables. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 97d405d-8e39-4e76-afe4-2f94b74ecfa2
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 175 out of 175 changed files in this pull request and generated no new comments.
Suppressed comments (1)
src/coreclr/vm/exceptmacros.h:220
QCallExceptionis custom-marshalled as aninton the managed side, but the native side now defines it as a struct. Since the managed/native ABI contract depends on this staying a singleINT32, add astatic_assertto prevent accidental layout changes from silently breaking QCall exception propagation.
Rename the managed and native status carrier to QCallExceptionStatus and update its custom marshaller. Restore runtime-neutral Objective-C wrappers, align the AssemblyName declaration, and remove exception capture from the non-throwing GC mode helper. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 97d405d-8e39-4e76-afe4-2f94b74ecfa2
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 174 out of 174 changed files in this pull request and generated 1 comment.
Suppressed comments (1)
src/coreclr/vm/excep.cpp:6713
OBJECTREF throwablecreated fromExInfo::CreateThrowable(...)is used withoutGCPROTECT. In cooperative mode, the thread can be suspended for GC before the reference is published to a scanned root (TLS), which risks losing the throwable beforeSetThrowablestores it.
| OBJECTREF orThrowable = CLRException::GetThrowableFromException(pException); | ||
| CONSISTENCY_CHECK(orThrowable != NULL); | ||
| pQCallException->SetThrowable(orThrowable); |
|
I built Release runtime + libraries at the mainline parent ( Benchmark source, full result table, methodology, and reproduction commands: https://gist.github.com/davidwrighton/3596168f4db88a825f6038ccecac13fe Note This benchmark analysis and comment were generated with GitHub Copilot. |
| // Licensed to the .NET Foundation under one or more agreements. | ||
| // The .NET Foundation licenses this file to you under the MIT license. | ||
|
|
||
| using System.Diagnostics; | ||
| using System.Runtime.ExceptionServices; | ||
| using System.Runtime.InteropServices.Marshalling; | ||
| using System.Threading; | ||
|
|
||
| namespace System.Runtime.CompilerServices | ||
| { | ||
| [NativeMarshalling(typeof(QCallExceptionStatusMarshaller))] | ||
| internal readonly struct QCallExceptionStatus | ||
| { | ||
| } | ||
|
|
||
| [CustomMarshaller(typeof(QCallExceptionStatus), MarshalMode.ManagedToUnmanagedOut, typeof(QCallExceptionStatusMarshaller))] | ||
| internal struct QCallExceptionStatusMarshaller | ||
| { | ||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| public void FromUnmanaged(int exceptionPending) | ||
| { | ||
| if (exceptionPending == 1) | ||
| { | ||
| HandleException(); | ||
| } | ||
| } | ||
|
|
||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| public QCallExceptionStatus ToManaged() => default; | ||
|
|
||
| [MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
| public void Free() { } | ||
|
|
||
| [MethodImpl(MethodImplOptions.NoInlining)] | ||
| private static void HandleException() | ||
| { | ||
| Exception exception = Thread.GetAndClearQCallException(); | ||
|
|
||
| // Throw during unmarshalling so QCall exception propagation remains as close as | ||
| // possible to throwing directly from native code, as QCalls did previously. | ||
| ExceptionDispatchInfo.Throw(exception); | ||
| } | ||
| } | ||
| } |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
Resolve QCall signature conflicts by preserving upstream API updates while retaining explicit exception-status propagation for QCalls that use BEGIN_QCALL. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 97d405d-8e39-4e76-afe4-2f94b74ecfa2
Squash the LibraryImportErrorHandler branch changes into one independently revertable commit, including hidden-return-value handling and generator tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 97d405d-8e39-4e76-afe4-2f94b74ecfa2
Return pointer-sized exception statuses from native QCalls and process them through LibraryImport hidden-return error handlers. Preserve exact exceptions with GC handles, recreate special exceptions through the runtime, remove thread-local storage, and regenerate WebAssembly helpers. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 97d405d-8e39-4e76-afe4-2f94b74ecfa2
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 97d405d-8e39-4e76-afe4-2f94b74ecfa2
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 97d405d-8e39-4e76-afe4-2f94b74ecfa2
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: b31492bf-57a2-4c93-8e29-1bc8e555289d
Release the caught native exception after transferring its throwable to the QCall status, and preserve the previous customer-visible COM exception stack trace. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: df97bfcc-e3cb-470b-be04-ac63dfebcb4a
Summary
BEGIN_QCALL/END_QCALLthrough anout QCallExceptionStatusvalue using a stateful source-generated custom marshallerQCallExceptionStatusMarshaller.FromUnmanagedInlinedCallFrameduring native exception capture instead of retaining release-build frame and current-thread localsTesting
build.cmd clr+libs -c Checked(0 warnings, 0 errors)build.cmd mono+libs(0 warnings, 0 errors)build.cmd clr+libs -os browser -c Debug(0 warnings, 0 errors)build.cmd clr.corelib -os osx -a x64 -c Debug(0 warnings, 0 errors)build.cmd clr.runtime -a x86 -c Checked(0 warnings, 0 errors)src\tasks\WasmAppBuilder\generate-coreclr-helpers.cmd -c DebugAmbiguousImplementationExceptionruntime test (exit code 100; exercises 12 sequential exceptions)BEGIN_QCALLimplementations migrated and no original non-BEGIN_QCALLimplementations migratedgit diff --checkThe WASI build compiles the affected CoreCLR and generated helper translation units, then fails at the existing final-link issues for
PAL_ProbeMemory,shm_open, andshm_unlink.Note
This pull request description was generated by GitHub Copilot.