gpt4 book ai didi

c# - 为什么 Mono 不能支持 AOT 的通用接口(interface)实例化?

转载 作者:太空狗 更新时间:2023-10-29 20:56:15 32 4
gpt4 key购买 nike

Mono 文档有一个关于 full AOT 的代码示例不支持通用接口(interface)实例化:

interface IFoo<T> {
...
void SomeMethod();
}

它说:

Since Mono has no way of determining from the static analysis what method will implement the interface IFoo<int>.SomeMethod this particular pattern is not supported."



所以我认为编译器不能在类型推断下使用这种方法。但是我仍然无法理解完整 AOT 限制的根本原因。

Unity AOT script restrictions仍然存在类似问题.在以下代码中:
using UnityEngine;
using System;

public class AOTProblemExample : MonoBehaviour, IReceiver
{
public enum AnyEnum {
Zero,
One,
}

void Start() {
// Subtle trigger: The type of manager *must* be
// IManager, not Manager, to trigger the AOT problem.
IManager manager = new Manager();
manager.SendMessage(this, AnyEnum.Zero);
}

public void OnMessage<T>(T value) {
Debug.LogFormat("Message value: {0}", value);
}
}

public class Manager : IManager {
public void SendMessage<T>(IReceiver target, T value) {
target.OnMessage(value);
}
}

public interface IReceiver {
void OnMessage<T>(T value);
}

public interface IManager {
void SendMessage<T>(IReceiver target, T value);
}

我对此感到困惑:

The AOT compiler does not realize that it should generate code for the generic method OnMessage with a T of AnyEnum, so it blissfully continues, skipping this method. When that method is called, and the runtime can’t find the proper code to execute, it gives up with this error message.



为什么 JIT 可以推断类型,但 AOT 不知道类型?谁能提供详细的答案?

最佳答案

在描述问题之前,请考虑以下来自 another answer of mine 的摘录描述了支持动态代码生成的平台上的泛型情况:

In C# generics, the generic type definition is maintained in memory at runtime. Whenever a new concrete type is required, the runtime environment combines the generic type definition and the type arguments and creates the new type (reification). So we get a new type for each combination of the type arguments, at runtime.



运行时这个短语是这个的关键,因为它把我们带到了另一点:

This implementation technique depends heavily on runtime support and JIT-compilation (which is why you often hear that C# generics have some limitations on platforms like iOS, where dynamic code generation is restricted).



那么完整的 AOT 编译器是否也可以做到这一点?这绝对是可能的。但这容易吗?

a paper from Microsoft Research on pre-compiling .NET generics它描述了泛型与 AOT 编译的交互,突出了一些潜在的问题并提出了解决方案。在这个答案中,我将使用那篇论文来尝试说明为什么 .NET 泛型还没有被广泛预编译(还)。

一切都必须被实例化

考虑你的例子:
IManager manager = new Manager();
manager.SendMessage(this, AnyEnum.Zero);

显然我们正在调用方法 IManager.SendMessage<AnyEnum>在这里,因此完全 AOT 编译器需要编译该方法。

但这是一个接口(interface)调用,它实际上是一个虚拟调用,这意味着我们无法提前知道将调用接口(interface)方法的哪个实现。

JIT 编译器不关心这个问题。当有人尝试运行尚未编译的方法时,JIT 将收到通知,它会延迟编译该方法。

相反,完全 AOT 编译器无法访问所有这些运行时类型信息。因此,它必须悲观地编译接口(interface)的所有实现上所有可能的泛型方法实例。 (或者只是放弃而不提供该功能。)

泛型可以无限递归
object M<T>(long n)
{
if (n == 1)
{
return new T[]();
}
else
{
return M<T[]>(n - 1);
}
}

实例化 M<int>() ,编译器需要实例化 int[]M<int[]>() .实例化 M<int[]>() ,编译器需要实例化 int[][]M<int[][]>() .实例化 M<int[][]>() ,编译器需要实例化 int[][][]M<int[][][]>() .

这可以通过使用代表性实例来解决(就像 JIT 编译器使用的那样)。这意味着所有引用类型的泛型参数都可以共享它们的代码。所以:
  • int[][] , int[][][] , int[][][][] (等等)都可以共享相同的代码,因为它们是引用数组。
  • M<int[]> , M<int[][]> , M<int[][][]> (等等)都可以共享相同的代码,因为它们对引用进行操作。

  • 程序集需要拥有它们的泛型......

    由于 C# 程序是在程序集中编译的,因此很难确切地告诉谁应该“拥有”每种类型的哪个实例化。
  • Assembly1声明类型 G<T> .
  • Assembly2 (引用 Assembly1)实例化类型 G<int> .
  • Assembly3 (引用 Assembly1)实例化类型 G<int>以及。
  • AssemblyX (引用以上所有)想用G<int> .

  • 哪个程序集可以编译实际 G<int> ?如果它们碰巧是独立的库,那么 Assembly2也不是 Assembly3无需每个人都拥有 G<int> 的副本即可编译.所以我们已经在研究重复的 native 代码。

    ...并且这些泛型仍然必须彼此兼容

    但是,当 AssemblyX被编译,这是 G<int>的副本它应该使用吗?显然,它必须能够同时处理这两种情况,因为它可能需要接收 G<int>来自或发送 G<int>到任一大会。

    但更重要的是,在 C# 中,不能有两种完全限定名称相同但结果不兼容的类型。换句话说:
    G<int> obj = new G<int>();

    以上内容永远不会失败,理由是 G<int> (变量的类型)是 G<int>来自 Assembly2G<int> (构造函数的类型)是 G<int>来自 Assembly3 .如果它因为这样的原因失败,我们就不再使用 C# 了!

    所以这两种类型都需要存在并且它们需要透明兼容,即使它们是单独编译的。为此,类型句柄需要在链接时以保留语言语义的方式进行操作,包括它们应该可以相互分配的事实,它们的类型句柄应该比较相等(例如,当使用 typeof ),依此类推。

    关于c# - 为什么 Mono 不能支持 AOT 的通用接口(interface)实例化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37376258/

    32 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com