Skip to content

[browser][coreCLR] no COM, no swift, no x86 intrinsics#125083

Draft
pavelsavara wants to merge 1 commit intodotnet:mainfrom
pavelsavara:browser_trim_COM
Draft

[browser][coreCLR] no COM, no swift, no x86 intrinsics#125083
pavelsavara wants to merge 1 commit intodotnet:mainfrom
pavelsavara:browser_trim_COM

Conversation

@pavelsavara
Copy link
Member

@pavelsavara pavelsavara commented Mar 2, 2026

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:

  1. ILLink descriptor roots generated from corelib.h and rexcep.h — the descriptor generator processes DEFINE_CLASS/DEFINE_EXCEPTION entries and creates root entries that tell the linker to preserve types and methods.
  2. Reverse P/Invoke stubs generated by PInvokeCollector.cs for [UnmanagedCallersOnly] methods on types that are unsupported on browser.
  3. [CompExactlyDependsOn(typeof(...))] attribute metadata — this R2R-only attribute creates hard metadata type references (via typeof()) 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.h

Guard InvalidOleVariantTypeException, MarshalDirectiveException, COMException, ExternalException, and SEHException with #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 defines FOR_ILLINK).

3. Exclude ComVariant from WASM ILLink descriptors

File: src/coreclr/vm/corelib.h

Guard COMVARIANT DEFINE_CLASS with #if !defined(TARGET_WASM) || !defined(FOR_ILLINK) to prevent rooting System.Runtime.InteropServices.Marshalling.ComVariant on WASM.

4. Exclude Swift interop types from WASM ILLink descriptors

File: src/coreclr/vm/corelib.h

Guard SwiftSelf, SwiftSelf<T>, SwiftError, and SwiftIndirectResult DEFINE_CLASS entries with #if !defined(TARGET_WASM) || !defined(FOR_ILLINK). Swift interop is not supported on WASM. The C++ code in callstubgenerator.cpp and stubgen.cpp still has access to CLASS__SWIFT_* constants during native compilation (since FOR_ILLINK is 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.xml

The GetFunctionPointer method on ComponentActivator was unconditionally rooted. Now gated behind the System.Runtime.InteropServices.EnableConsumingManagedCodeFromNativeHosting feature switch, matching the other ComponentActivator methods in the same file.

6. Filter [UnsupportedOSPlatform("browser")] types from reverse P/Invoke stubs

Files: src/tasks/WasmAppBuilder/coreclr/PInvokeCollector.cs, src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.PlatformNotSupported.cs

  • Add IsUnsupportedOnBrowser() helper to PInvokeCollector.DoesMethodHaveCallbacks() — skips generating reverse P/Invoke callback stubs for methods on types annotated with [UnsupportedOSPlatform("browser")].
  • Add [UnsupportedOSPlatform("browser")] to ComActivator.PlatformNotSupported.cs so its [UnmanagedCallersOnly] methods (GetClassFactoryForTypeInternal, RegisterClassForTypeInternal, UnregisterClassForTypeInternal) are excluded from the generated stubs.

7. Strip [CompExactlyDependsOn] attribute on browser/WASI builds

File: src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/CompExactlyDependsOnAttribute.cs

Expand the existing [Conditional("unnecessary")] guard from #if MONO to #if MONO || TARGET_BROWSER || TARGET_WASI. This attribute is only needed for Ready2Run compilation, which browser and WASI targets do not use. The typeof(AdvSimd.Arm64) etc. arguments in 40+ methods across SPCL create hard metadata references that prevent the linker from trimming System.Runtime.Intrinsics.Arm (and X86) 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.cpp

Regenerated to reflect the ComActivator exclusion (3 stubs removed from reverse callbacks) and removal of System.Net.Primitives socket address P/Invokes that were removed upstream.

Design: The FOR_ILLINK guard pattern

The 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.

  • C++ compiler: FOR_ILLINK is never defined → condition is always true → entries are included
  • ILLink descriptor generator (CreateRuntimeRootILLinkDescriptorFile): passes DefineConstants=$(DefineConstants);FOR_ILLINK with a simple #if parser that treats unknown expressions (like defined() with &&/||) as false → entries are excluded on WASM
  • Non-WASM ILLink generation: TARGET_WASM is not defined → condition is true → entries are included

Testing

The build was verified with .\build.cmd -os browser -subset clr -c Debug /p:RuntimeFlavor=CoreCLR.

@pavelsavara pavelsavara added this to the 11.0.0 milestone Mar 2, 2026
@pavelsavara pavelsavara self-assigned this Mar 2, 2026
Copilot AI review requested due to automatic review settings March 2, 2026 23:23
@pavelsavara pavelsavara added arch-wasm WebAssembly architecture area-VM-coreclr size-reduction Issues impacting final app size primary for size sensitive workloads os-browser Browser variant of arch-wasm labels Mar 2, 2026
@dotnet-policy-service dotnet-policy-service bot added the linkable-framework Issues associated with delivering a linker friendly framework label Mar 2, 2026
@dotnet-policy-service
Copy link
Contributor

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

Copy link
Contributor

Copilot AI left a comment

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 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 annotates ComActivator accordingly.
  • Gates ILLink rooting for ComponentActivator.GetFunctionPointer behind the existing native-hosting feature switch.
  • Adds TARGET_WASM guards 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.

Comment on lines +127 to +129
if (IsUnsupportedOnBrowser(method.DeclaringType))
return false;

Copy link

Copilot AI Mar 2, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasm WebAssembly architecture area-VM-coreclr linkable-framework Issues associated with delivering a linker friendly framework os-browser Browser variant of arch-wasm size-reduction Issues impacting final app size primary for size sensitive workloads

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants