Type loader support for static virtual methods (#71321)
authorMichal Strehovský <MichalStrehovsky@users.noreply.github.com>
Tue, 28 Jun 2022 04:38:49 +0000 (13:38 +0900)
committerGitHub <noreply@github.com>
Tue, 28 Jun 2022 04:38:49 +0000 (13:38 +0900)
commit844b0999fde67cdbaa7acb0f398ea1b066a2b8c7
tree549df18ed0d731252c0a093ab9b88133e26b71ec
parent812f8f56f4ce09d91ef6d436ccf88f4ccabc9687
Type loader support for static virtual methods (#71321)

Fixes #67745.

Support for static virtual methods that was added in #66084 was enough for compile-time resolution of static virtual methods, but didn't cover dynamic code. For example, given following code:

```csharp
interface IFoo { static virtual void Frob(); }
class SomeCaller<T> where T : IFoo { ... T.Frob(); }
class SomeClass : IFoo { ... }
```

If we do `typeof(SomeCaller<>).MakeGenericType(typeof(SomeClass)` at runtime, the runtime has to find what method implements `IFoo.Frob` on `SomeClass` and ensure proper data structures are generated for `SomeCaller<SomeClass>` so that the call lands in the right spot at runtime.

On a high level, what we need:
* Change to the compiler to generate extra data ("interface dispatch maps") that lets us find an implementation of interface method X on a given type Y.
* Change to the runtime to read the new data structure.
* Change to the compiler to generate extra method bodies for types that can potentially be used with MakeGeneric at runtime. This is an overapproximation since we don't know the set of types that will really be used.
* Change to type loader data structures to capture when shared generic code needs to do this mapping, and change the code in the compiler that emits it, and to the type loader that reads it.

I've made it so that the dispatch logic between instance and static methods is shared. It's not strictly necessary for both to go into the same data structure, but it prevents duplicating the code on the emission and reading side. The side effect of that is that static virtual methods now go into the sealed vtable. We have to put them somewhere. This spot is as good as any.

I've also had to make a small change to the ordering of data structure generation within the type loader. I've made it so that EEType/MethodTable structures are fully populated before we start filling out generic dictionaries. This prevents us from calling into the runtime dispatch logic with EETypes/MethodTables that are not actually built yet. I really didn't want to duplicate the dispatch logic into the type loader.
21 files changed:
src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs
src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/CachedInterfaceDispatch.cs
src/coreclr/nativeaot/Runtime.Base/src/System/Runtime/DispatchResolve.cs
src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs
src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs
src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/EETypeCreator.cs
src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs
src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs
src/coreclr/tools/Common/Compiler/MethodExtensions.cs
src/coreclr/tools/Common/Internal/NativeFormat/NativeFormat.cs
src/coreclr/tools/Common/Internal/Runtime/RuntimeConstants.cs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericLookupResult.cs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchMapNode.cs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/SealedVTableNode.cs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/VTableSliceNode.cs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/VirtualMethodUseNode.cs
src/coreclr/tools/aot/ILCompiler.RyuJit/JitInterface/CorInfoImpl.RyuJit.cs
src/tests/nativeaot/SmokeTests/DeadCodeElimination/DeadCodeElimination.cs
src/tests/nativeaot/SmokeTests/UnitTests/Interfaces.cs