Skip to content

Add support for pre-compiling interop type maps in crossgen2#124352

Open
jkoritzinsky wants to merge 33 commits intodotnet:mainfrom
jkoritzinsky:typemap-r2r
Open

Add support for pre-compiling interop type maps in crossgen2#124352
jkoritzinsky wants to merge 33 commits intodotnet:mainfrom
jkoritzinsky:typemap-r2r

Conversation

@jkoritzinsky
Copy link
Member

@jkoritzinsky jkoritzinsky commented Feb 12, 2026

Use the native format to encode the information like in NAOT. For references to types, encode as an (int, int) pair pointing to an R2R import fixup for a given type handle.

This PR precompiles each assembly's type maps independently. It also precompiles the TypeMapAssemblyTargets attributes into a hash table mapping the group type to a sequence of Module*, encoded via fixups with a similar entry formatting to type references (an (int, int) pair pointing to a "helper fixup" with the module override + READYTORUN_HELPER_Module).

Fixes #123678
Depends on #124247
Depends on #124202

Copilot AI review requested due to automatic review settings February 12, 2026 19:49
@dotnet-policy-service dotnet-policy-service bot added the linkable-framework Issues associated with delivering a linker friendly framework label Feb 12, 2026
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 pull request adds support for pre-compiling interop type maps in crossgen2/ReadyToRun images. Instead of processing TypeMap attributes at runtime, the compiler encodes them into native format hash tables similar to how NativeAOT works. The implementation introduces three new ReadyToRun sections (ExternalTypeMaps, ProxyTypeMaps, and TypeMapAssemblyTargets) that store pre-computed type mappings.

Changes:

  • Adds native code to read pre-cached type map entries from R2R sections during runtime lookup
  • Implements compiler infrastructure to generate type map hash tables in native format
  • Modifies TypeMapMetadata collection to support two modes: Traverse (for NativeAOT) and Record (for R2R)
  • Bumps ReadyToRun minor version to 18.1

Reviewed changes

Copilot reviewed 46 out of 46 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TypeMapLazyDictionary.cs Adds QCall methods to query pre-cached type maps and integrates them into the lazy dictionary lookup path
src/coreclr/vm/readytoruninfo.h Declares member variables and methods for the three new R2R sections
src/coreclr/vm/readytoruninfo.cpp Implements hash table lookups for pre-cached external/proxy type maps and assembly targets with critical bugs
src/coreclr/vm/qcallentrypoints.cpp Registers new QCall entry points for type map queries
src/coreclr/vm/nativeformatreader.h Adds string decoding/comparison utilities for native format reader
src/coreclr/vm/corelib.h Adds field mapping for CallbackContext structure
src/coreclr/vm/binder.cpp Adds include for assemblynative.hpp
src/coreclr/vm/assemblynative.hpp Updates CallbackContext native structure and declares new QCall signatures
src/coreclr/vm/assemblynative.cpp Modifies ProcessAttributes to check for and process pre-cached type maps before falling back to attributes
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/TypeMapAssemblyTargetsNode.cs Generates native hash table encoding assembly targets per type map group
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunTypeMapManager.cs R2R-specific type map manager that creates nodes for each module's type maps
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunProxyTypeMapNode.cs Encodes proxy type map entries as native format hash tables
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunExternalTypeMapNode.cs Encodes external type map entries as native format hash tables
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs Initializes ImportReferenceProvider
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunSymbolNodeFactory.cs Changes return types from ISymbolNode to Import for consistency
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs Integrates TypeMapManager into per-assembly R2R header generation
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ReadyToRunModuleSignature.cs New signature type for module helper fixups
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ReadyToRunHeaderNode.cs Renames HeaderNode to ReadyToRunHeaderNode and adds overload for Add method
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ManifestMetadataTableNode.cs Removes incorrect assertion
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ImportReferenceProvider.cs Provides unified interface for encoding type/module references as R2R import fixups
src/coreclr/tools/aot/ILCompiler/Program.cs Updates TypeMapMetadata.CreateFromAssembly calls with new parameters
src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/TrimmingDriver.cs Updates TypeMapMetadata.CreateFromAssembly calls with new parameters
src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj Adds new compiler source files to project
src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj Moves TypeMap files to shared Common location
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/UsageBasedTypeMapManager.cs Refactors to use helper methods for node creation
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs Updates TypeMapManager integration to use INativeFormatTypeReferenceProvider
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ProxyTypeMapNode.cs Changes base class to SortableDependencyNode and updates signature
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InvalidProxyTypeMapNode.cs Changes base class to SortableDependencyNode and updates signature
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InvalidExternalTypeMapNode.cs Changes base class to SortableDependencyNode and updates signature
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternalTypeMapNode.cs Changes base class to SortableDependencyNode and updates signature
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AnalyzedProxyTypeMapNode.cs Changes base class to SortableDependencyNode and updates signature
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/AnalyzedExternalTypeMapNode.cs Changes base class to SortableDependencyNode and updates signature
src/coreclr/tools/Common/Internal/Runtime/ModuleHeaders.cs Bumps R2R minor version to 18.1 and adds new section type enum values
src/coreclr/tools/Common/Internal/Runtime/MetadataBlob.cs Removes obsolete ExternalTypeMap/ProxyTypeMap blob enum values
src/coreclr/tools/Common/Compiler/TypeMapMetadata.cs Extensive refactoring to support TypeMapAssemblyTargetsMode and pending map merging
src/coreclr/tools/Common/Compiler/TypeMapManager.cs Moves to shared Common location and adds ReadyToRun-specific method
src/coreclr/tools/Common/Compiler/ProxyTypeMapObjectNode.cs Updates to use TypeMapManager and INativeFormatTypeReferenceProvider
src/coreclr/tools/Common/Compiler/IProxyTypeMapNode.cs Changes visibility to internal and conditionally compiles ToAnalysisBasedNode
src/coreclr/tools/Common/Compiler/INativeFormatTypeReferenceProvider.cs New interface for abstracting type/method reference encoding
src/coreclr/tools/Common/Compiler/IExternalTypeMapNode.cs Changes visibility to internal and conditionally compiles ToAnalysisBasedNode
src/coreclr/tools/Common/Compiler/ExternalTypeMapObjectNode.cs Updates to use TypeMapManager and INativeFormatTypeReferenceProvider
src/coreclr/tools/Common/Compiler/DependencyAnalysis/SortableDependencyNode.cs Renames ReadyToRunHeaderNode to GlobalHeaderNode in enum
src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/TypeMapLazyDictionary.NativeAot.cs Updates to use ReadyToRunSectionType instead of ReflectionMapBlob
src/coreclr/inc/readytorun.h Adds new R2R section type enum values and version comment
src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/TypeMap.cs Adds test coverage for new UsedTypeMapUniverse type map group

Copilot AI review requested due to automatic review settings February 13, 2026 00:16
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

Copilot reviewed 46 out of 46 changed files in this pull request and generated 5 comments.

Comments suppressed due to low confidence (3)

src/coreclr/tools/Common/Compiler/ProxyTypeMapObjectNode.cs:17

  • This file has an unused using System.Formats.Tar; import in the header. Even though it’s not referenced by the code here, it can still cause compile breaks if the namespace isn’t available for some target frameworks/configurations, and it adds noise. Please remove the unused using directive.
    src/coreclr/tools/Common/Compiler/ExternalTypeMapObjectNode.cs:51
  • GetSection now always returns ObjectNodeSection.DataSection. Previously the section choice followed the external references table (often ReadOnlyDataSection on Windows/relative-pointer targets). Forcing writable data can have security/size implications and may change object layout unexpectedly. Consider keeping the prior behavior (e.g., mirror the common fixups table’s section selection) or explicitly justify why RW data is required.
    src/coreclr/tools/Common/Compiler/ProxyTypeMapObjectNode.cs:55
  • Same as ExternalTypeMapObjectNode: GetSection is hardcoded to DataSection, which may unnecessarily make the typemap blob writable on platforms that previously placed it in ReadOnlyDataSection. Consider restoring the previous section selection logic to avoid regressions in memory protections/layout.

Copilot AI review requested due to automatic review settings February 14, 2026 00:51
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

Copilot reviewed 44 out of 44 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (2)

src/coreclr/tools/Common/Compiler/ProxyTypeMapObjectNode.cs:47

  • The Size property is removed from the interface but still exists in the implementation. The ProxyTypeMapObjectNode class declares public int Size { get; private set; } at line 47, but after removing the INodeWithSize interface, this property is no longer used or set. Remove the unused Size property.
    src/coreclr/tools/Common/Compiler/ExternalTypeMapObjectNode.cs:45
  • The Size property is removed from the interface but still exists in the implementation. The ExternalTypeMapObjectNode class declares public int Size { get; private set; } at line 45 and sets it at line 36, but after removing the INodeWithSize interface, this property is no longer used. Remove the unused Size property and the assignment at line 36.

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

Copilot reviewed 50 out of 50 changed files in this pull request and generated 4 comments.

Copilot AI review requested due to automatic review settings March 13, 2026 18:43
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

Copilot reviewed 52 out of 52 changed files in this pull request and generated 4 comments.

Comments suppressed due to low confidence (3)

src/coreclr/tools/Common/Compiler/TypeMapMetadata.cs:51

  • IExternalTypeMap.ThrowingMethodStub / IProxyTypeMap.ThrowingMethodStub are declared as non-nullable MethodDesc, but most maps appear to have no throwing stub (callers check is not null). This will likely produce nullable warnings (often errors) and misrepresents intent. Make these properties nullable (MethodDesc?) and adjust uses accordingly.
    src/coreclr/tools/Common/Compiler/TypeMapMetadata.cs:51
  • IExternalTypeMap.ThrowingMethodStub / IProxyTypeMap.ThrowingMethodStub are declared as non-nullable MethodDesc, but consumers treat these as optional (is not null). This is likely to cause nullable warnings-as-errors and misrepresents intent (valid maps have no stub). Make these properties nullable (MethodDesc?) and update call sites accordingly.
    src/coreclr/tools/Common/Compiler/ExternalTypeMapObjectNode.cs:16
  • ExternalTypeMapObjectNode is now public while most dependency-analysis nodes in this area are internal. Unless this type is intended to be a supported public surface, consider keeping it internal to avoid accidentally expanding the tool API surface.

Copilot AI review requested due to automatic review settings March 13, 2026 23:40
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

Copilot reviewed 52 out of 52 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

src/coreclr/tools/Common/Compiler/ExternalTypeMapObjectNode.cs:17

  • ExternalTypeMapObjectNode was changed from internal to public, but ProxyTypeMapObjectNode remains internal. If this isn't required, consider keeping it internal (or making both consistent) to avoid unintentionally expanding the public surface area of the compiler tool assemblies.

Copilot AI review requested due to automatic review settings March 14, 2026 04:37
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

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

Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Copilot AI review requested due to automatic review settings March 14, 2026 18:05
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

Copilot reviewed 52 out of 52 changed files in this pull request and generated 4 comments.

Comment on lines +41 to +50
public Vertex CreateTypeMap(NodeFactory factory, NativeWriter writer, Section section, INativeFormatTypeReferenceProvider externalReferences)
{
if (map.ThrowingMethodStub is not null)
{
// We don't write out the throwing method stub for R2R
// as emitting loose methods is not supported/very expensive.
// Instead, we defer to the runtime to generate the type map
// and throw on error cases.
return section.Place(writer.GetUnsignedConstant(0)); // Invalid type map state
}
Comment on lines +39 to +50
public Vertex CreateTypeMap(NodeFactory factory, NativeWriter writer, Section section, INativeFormatTypeReferenceProvider ProxyReferences)
{
if (map.ThrowingMethodStub is not null)
{
// We don't write out the throwing method stub for R2R
// as emitting loose methods is not supported/very expensive.
// Also, matching CoreCLR's exact set of exceptions is difficult
// in the managed type system.
// Instead, we defer to the runtime to generate the type map
// and throw on error cases.
return section.Place(writer.GetUnsignedConstant(0)); // Invalid type map state
}
Comment on lines +39 to +41
public Vertex CreateTypeMap(NodeFactory factory, NativeWriter writer, Section section, INativeFormatTypeReferenceProvider ProxyReferences)
{
if (map.ThrowingMethodStub is not null)
Comment on lines +25 to +30
foreach (string line in r2rDumpLines)
{
if (line.StartsWith("ExternalTypeMap") || line.StartsWith("ProxyTypeMap") || line.StartsWith("TypeMapAssemblyTargets"))
{
throw new InvalidOperationException($"Unexpected TypeMap section found in R2R dump for file with no type maps: {line}");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-crossgen2-coreclr linkable-framework Issues associated with delivering a linker friendly framework

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

TypeMapLazyDictionary is slow in android apps - Can we preconstruct the dictionary?

5 participants