[browser][coreCLR] no COM, no swift, no x86 intrinsics#125083
[browser][coreCLR] no COM, no swift, no x86 intrinsics#125083pavelsavara wants to merge 1 commit intodotnet:mainfrom
Conversation
|
Tagging subscribers to this area: @agocke |
There was a problem hiding this comment.
Pull request overview
This PR aims to reduce trimmed size for browser-WASM CoreCLR builds by removing/gating roots and native support code for features that aren’t supported in the browser (COM/interop-related pieces, DynamicInterfaceCastable, Swift interop, and intrinsics metadata rooting).
Changes:
- Filters reverse P/Invoke stub generation for types marked
[UnsupportedOSPlatform("browser")]and annotatesComActivatoraccordingly. - Gates ILLink rooting for
ComponentActivator.GetFunctionPointerbehind the existing native-hosting feature switch. - Adds
TARGET_WASMguards to exclude DynamicInterfaceCastable native support on WASM and trims related ILLink roots / metadata retention paths.
Reviewed changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| src/tasks/WasmAppBuilder/generate-coreclr-helpers.cmd | Updates helper generation script used for CoreCLR WASM callhelper regeneration. |
| src/tasks/WasmAppBuilder/coreclr/PInvokeCollector.cs | Skips generating reverse P/Invoke callback stubs for types unsupported on browser. |
| src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/CompExactlyDependsOnAttribute.cs | Removes CompExactlyDependsOnAttribute metadata for browser/WASI builds to improve trimming. |
| src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.Shared.xml | Gates ComponentActivator.GetFunctionPointer rooting behind the native-hosting feature switch. |
| src/coreclr/vm/wasm/callhelpers-reverse.cpp | Regenerated reverse thunk table reflecting removed callbacks. |
| src/coreclr/vm/wasm/callhelpers-pinvoke.cpp | Regenerated P/Invoke table reflecting upstream removals. |
| src/coreclr/vm/virtualcallstub.cpp | Removes DynamicInterfaceCastable resolver path from WASM builds. |
| src/coreclr/vm/rexcep.h | Attempts to exclude interop exception types from WASM ILLink descriptor generation. |
| src/coreclr/vm/methodtable.cpp | Removes IDynamicInterfaceCastable special method resolution on WASM. |
| src/coreclr/vm/jithelpers.cpp | Removes IDynamicInterfaceCastable cast path on WASM. |
| src/coreclr/vm/dynamicinterfacecastable.h | Wraps DynamicInterfaceCastable API surface out of WASM builds. |
| src/coreclr/vm/dynamicinterfacecastable.cpp | Wraps DynamicInterfaceCastable implementation out of WASM builds. |
| src/coreclr/vm/corelib.h | Attempts to exclude Swift interop and ComVariant from WASM ILLink descriptor generation; removes DynamicInterfaceCastableHelpers from WASM. |
| src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.PlatformNotSupported.cs | Marks ComActivator as unsupported on browser to suppress reverse stub generation. |
| if (IsUnsupportedOnBrowser(method.DeclaringType)) | ||
| return false; | ||
|
|
There was a problem hiding this comment.
IsUnsupportedOnBrowser(method.DeclaringType) is called once per method, but it reflects over the declaring type’s attributes each time. Since this collector can scan many methods per type, consider caching the unsupported-on-browser result per Type (similar to _assemblyDisableRuntimeMarshallingAttributeCache) to avoid repeated reflection overhead during stub generation.
c066985 to
77b2da7
Compare
Trim dead interop/intrinsics code from browser-WASM CoreCLR builds
Summary
This PR reduces the trimmed size of browser-WASM CoreCLR apps by removing ILLinker roots and native code for features that cannot run in the browser: COM interop, Dynamic Interface Castable, Swift interop, and hardware intrinsics metadata.
Motivation
When building trimmed browser-WASM apps with CoreCLR, several managed types survive trimming despite being unreachable at runtime. These types are kept alive by:
corelib.handrexcep.h— the descriptor generator processesDEFINE_CLASS/DEFINE_EXCEPTIONentries and creates root entries that tell the linker to preserve types and methods.PInvokeCollector.csfor[UnmanagedCallersOnly]methods on types that are unsupported on browser.[CompExactlyDependsOn(typeof(...))]attribute metadata — this R2R-only attribute creates hard metadata type references (viatypeof()) that the linker follows, keeping entire intrinsics type hierarchies alive.Changes
1. Exclude COM/Interop exception types from WASM ILLink descriptors
Files:
src/coreclr/vm/rexcep.hGuard
InvalidOleVariantTypeException,MarshalDirectiveException,COMException,ExternalException, andSEHExceptionwith#if !defined(TARGET_WASM) || !defined(FOR_ILLINK). This excludes them from the generated ILLink descriptor on WASM while keeping them available for the C++ compiler (which never definesFOR_ILLINK).3. Exclude ComVariant from WASM ILLink descriptors
File:
src/coreclr/vm/corelib.hGuard
COMVARIANTDEFINE_CLASS with#if !defined(TARGET_WASM) || !defined(FOR_ILLINK)to prevent rootingSystem.Runtime.InteropServices.Marshalling.ComVarianton WASM.4. Exclude Swift interop types from WASM ILLink descriptors
File:
src/coreclr/vm/corelib.hGuard
SwiftSelf,SwiftSelf<T>,SwiftError, andSwiftIndirectResultDEFINE_CLASS entries with#if !defined(TARGET_WASM) || !defined(FOR_ILLINK). Swift interop is not supported on WASM. The C++ code incallstubgenerator.cppandstubgen.cppstill has access toCLASS__SWIFT_*constants during native compilation (sinceFOR_ILLINKis never defined for the C++ compiler).5. Gate ComponentActivator ILLink root behind feature switch
File:
src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.Shared.xmlThe
GetFunctionPointermethod onComponentActivatorwas unconditionally rooted. Now gated behind theSystem.Runtime.InteropServices.EnableConsumingManagedCodeFromNativeHostingfeature switch, matching the otherComponentActivatormethods in the same file.6. Filter
[UnsupportedOSPlatform("browser")]types from reverse P/Invoke stubsFiles:
src/tasks/WasmAppBuilder/coreclr/PInvokeCollector.cs,src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.PlatformNotSupported.csIsUnsupportedOnBrowser()helper toPInvokeCollector.DoesMethodHaveCallbacks()— skips generating reverse P/Invoke callback stubs for methods on types annotated with[UnsupportedOSPlatform("browser")].[UnsupportedOSPlatform("browser")]toComActivator.PlatformNotSupported.csso its[UnmanagedCallersOnly]methods (GetClassFactoryForTypeInternal,RegisterClassForTypeInternal,UnregisterClassForTypeInternal) are excluded from the generated stubs.7. Strip
[CompExactlyDependsOn]attribute on browser/WASI buildsFile:
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/CompExactlyDependsOnAttribute.csExpand the existing
[Conditional("unnecessary")]guard from#if MONOto#if MONO || TARGET_BROWSER || TARGET_WASI. This attribute is only needed for Ready2Run compilation, which browser and WASI targets do not use. Thetypeof(AdvSimd.Arm64)etc. arguments in 40+ methods across SPCL create hard metadata references that prevent the linker from trimmingSystem.Runtime.Intrinsics.Arm(andX86) type hierarchies. Stripping the attribute at compile time removes these metadata references.8. Regenerated callhelpers files
Files:
src/coreclr/vm/wasm/callhelpers-pinvoke.cpp,src/coreclr/vm/wasm/callhelpers-reverse.cppRegenerated to reflect the ComActivator exclusion (3 stubs removed from reverse callbacks) and removal of
System.Net.Primitivessocket address P/Invokes that were removed upstream.Design: The
FOR_ILLINKguard patternThe pattern
#if !defined(TARGET_WASM) || !defined(FOR_ILLINK)is used for entries that must remain in native C++ code (for the enum/constant generator) but should be excluded from the ILLink root descriptor on WASM.FOR_ILLINKis never defined → condition is always true → entries are includedCreateRuntimeRootILLinkDescriptorFile): passesDefineConstants=$(DefineConstants);FOR_ILLINKwith a simple#ifparser that treats unknown expressions (likedefined()with&&/||) as false → entries are excluded on WASMTARGET_WASMis not defined → condition is true → entries are includedTesting
The build was verified with
.\build.cmd -os browser -subset clr -c Debug /p:RuntimeFlavor=CoreCLR.