Skip to content

[Wasm RyuJIT] Interop/Pinvoke Design #124103

@kg

Description

@kg

Current Status

The current stub generator produces tables and C wrappers in order to support p/invoke and reverse p/invoke. The wrappers and tables are compiled with clang and linked into the runtime. The interpreter relies on these wrappers for managed-to-native and native-to-managed transitions. The current generator has to be run manually on all the assemblies that contain p/invokes in order to generate the new tables and wrappers for inclusion into the runtime.

The table used to locate wrappers is a simple linear array, not a hashtable or sorted array, which means it is trivial to add additional entries to it at the end - for example, at assembly load time.

New Generator Plan

The new stub generator will be integrated into crossgen2 as a mode that can run independently from codegen for managed methods and embed a table and wrappers into the wasm (WebCIL) module for each assembly, regardless of whether the assembly's managed code is AOTed. When the assembly is loaded we will copy the embedded table entries into the runtime's main table.

This is a separate concern from things like marshaling stubs, which already have partial support in crossgen2 but not full support. LibraryImport acts as a replacement for most of the stubs that crossgen2 does not support.

Stage 1

We will initially aim for parity with the current generator, and only generate what is absolutely necessary for things to work. So things like marshaling stubs will not be an implementation priority, and our priority is to generate the tables and stub code necessary to run a test application or library without any changes to the runtime.

This requires:

  • Managed-native transitions and their table entries
  • Native-managed (reverse pinvoke) transitions and their table entries
  • UnmanagedCallersOnly wrappers and their hashtable entries
  • WasmImportLinkage imports

All of the above will be embedded into the WebCIL module for each managed assembly, where the table entries will live in a data segment and the stubs will be exported native wasm functions.

The first step is to have crossgen2 be able to scan all the same assemblies as the current generator and produce the same list as the current generator, showing that we have support parity.

Stage 2

Once we are able to scan the assemblies correctly and generate the list, we want to start actually generating the stubs from the list. We can do this either via generating IL or generating wasm directly. Generating IL is the convention for this in the normal native runtime and in mono, but may prove problematic due to the managed calling convention we are planning to use.

We should start with managed-to-native transitions as they cover the vast majority of cases.

We will need to generate the stubs, export the stubs from the webcil module, generate the table containing the stubs, and generate a function pointer table that maps the entries in that table to the exported webcil stubs.

Stage 3

Next, we should implement reverse p/invoke and UnmanagedCallersOnly to enable use of native APIs that require callbacks, i.e. JSSynchronizationContext.

We will need to generate the stubs and export them from the webcil module. Everything else should be mostly the same as stage 2.

Stage 4

We should implement WasmImportLinkage, which requires generating a native wasm import for each p/invoke with import linkage. RyuJIT will also need to be updated to know how to call these imports directly instead of going through the normal function call machinery. We will need to update the part of the runtime C/JS that instantiates modules, so it knows how to resolve wasmimportlinkages. We will need to include metadata (either part of the wasm module as a custom section, or in a separate metadata file per-assembly) that specifies what these import linkages are and what they depend on.

Stage 5

Once crossgen2 is able to handle everything the old stub generator is used for, we can retire the old stub generator. This will require making sure crossgen2 is fully integrated into the build pipeline, being run on every managed assembly after trimming to generate the webcil envelope with stubs and tables that get loaded by the runtime.

Metadata

Metadata

Assignees

No one assigned

    Labels

    arch-wasmWebAssembly architecturearea-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions