RFC-0048:显式联合序数

RFC-0048:显式联合序数
状态已接受
领域
  • FIDL
说明

为了更好地协调可扩展联合(或简单联合)的 ABI 影响,我们提议进行一些更改,使灵活联合在语法上更接近于表格,并纠正目前有关重命名联合或联合成员的奇数 [2] 和过于严格的 ABI 限制。

作者
提交日期(年-月-日)2019-08-25
审核日期(年-月-日)2019-09-26

摘要

为了更好地对齐可扩展联合(或简称为 union)的 ABI 含义, 提议:

  1. 将变体成员的语法更改为需要显式序数 (类似于需要表序数)。
  2. 使用此显式序数,而不是之前实现的经过哈希处理 序数。
  3. 最后,我们更改传输格式,使并集序数为 64 位 (而不是 32 位)。

这些更改使灵活联合在语法上更接近于表格,并且 纠正奇怪的1 ABI 限制和过于严格的 ABI 限制 重命名联盟或联盟成员。

动机和设计

就类型而言,除了联合外,名称对 ABI 没有影响:枚举、位、 结构体和表都可以重命名,或者可以重命名其成员而不指定任何 而对二进制兼容性的担忧联合体有所不同,因为我们选择使用 分配变体序号的基于哈希的技术(请参阅 RFC-0061:可扩展 联合体)。

我们已经认识到这个缺点,并提出了解决方法:请参阅 意图实现:xunion 序数更改,这表明 更改哈希架构,使其仅包含成员名称。

相反,此方案更进一步,仅使用显式序数, 从而避免名称与 ABI 兼容性之间存在任何关联。我们认为 在并集声明中编写序数词时要多花些心思:迄今为止 表中的显式序数不再是问题, 为来自其他热门 IDL 的成员或变体编号的先例。

此外,为了进一步与表保持一致,我们要求序数必须是 从 1 开始依序分配,并且允许将关键字 reserved 用于 明确跳过联合变体。

仅对协议进行哈希处理

与类型不同,协议使用基于哈希的方法分配序数。这是 涉及两个关键应用场景:

  • 协议可以组合,因此我们需要一个全局序数 分配方案,以避免因距离较远而中断问题。请参阅 [RFC-0063: OrdinalRange, RFC-0020:接口序哈希, 和 RFC-0029: Increasing Method Ordinals(增加方法序数)。
  • 实际上全局唯一标识符可以极大地简化和增强 监控和跟踪需求等小提琴的关键在于 唯一标识方法调用。

这些用例无法转换为类型。

此方案的影响是,哈希仅适用于协议。还有 一个哈希方案,即 RFC-0029 中描述的方案。

64 位序数是标准的

目前,联合内嵌内容中有 4 个字节的填充:

  • 序数 (uint32)
  • 内边距 (uint32)
  • 信封(16 个字节)

相反,我们希望以 因此将序数更改为 64b一般来说,我们更倾向于无填充 结构,因为它们更高效(例如,不需要显式小米集) 或额外的编码表)。

请参阅实现策略部分,了解如何 软转换为 64 位序数。

JSON 线上格式

过去已经讨论过,在创建 JSON 传输格式时, 类型和成员对该格式的 ABI 有何影响。

按“线缆格式”分离 ABI 损坏会很有用基础。我们可以 从不同的属性中选出不同的值需要为 ABI 的罕见消息 与支持的所有可能的有线格式的兼容性将非常有限, 它们可以演变。另一些广告客户则应当尽可能采用更加灵活的规则。

接下来:稀疏表

我们已经讨论过如何支持稀疏表,即支持使用第三种布局 以及结构体。如果我们决定推出第 3 个选项 Strawman 语法会遵循此提议,而当前表的语法:

sparse_table Example {
    1: T1 field1;
    2: reserved; // deprecated
    3: T3 field3;
};

实施策略

为了实现软过渡,我们需要消除传统(32 位) 经过哈希处理的序数语法和提议的(64 位显式)序数语法。这个 可以通过以下方式实现:

  1. 添加 fidlc 形式的检查,以确保 32 位哈希序数的值 始终低于 N。例如,如果 N 为 512,则是哈希序数的十六进制值 必须至少为 0x200。
    • 经过哈希处理且小于或等于 <0x200 将导致编译错误,而 字段名称必须使用 [Selector=] 属性手动重命名。我们 请将 [Selector] 添加到相应字段中,然后再实现此变更 错别字。
    • 鉴于现有哈希架构的随机性,我们预计 错误发生的次数接近于零,因此人工解决方法 。
    • 添加此检查可有效地为[0..N] 显式序数,并确保不会与经过哈希处理的序数发生冲突。
  2. 当语言绑定解释序数值时: <ph type="x-smartling-placeholder">
      </ph>
    • 如果序数介于 [0, N) 之间,则序数为 64 位与明确。
    • 如果序数介于 [N, UINT32_MAX] 之间,则序数为 32 位且经过哈希处理。
    • 如果序数介于 [UINT32_MAX, UINT64_MAX) 之间,则绑定必须调用 并关闭带有顶角的频道。

工效学设计

大大简化了 ABI 工效学,只需拥有显式序数的语法成本极低。

文档和示例

至少:

向后兼容性

未使用显式序数语法定义的联合将继续使用 现有的 32 位哈希序数架构。因此,今天存在的并集将 继续与 API 和 ABI 兼容。

使用显式序数语法定义的并集将使用 64 位序数架构 。有关详情,请参阅实施 Strategy 部分介绍了如何同时支持 32 位 和 64 位序数方案

性能

改进非常小:由于对 switch() 语句可以更好地进行代码生成,因此该架构比经过哈希处理的序数更高效。

安全

无影响。

测试

照常,无关紧要。

缺点、替代方案和未知问题

替代方案:仅对成员名称进行序数哈希处理

请参阅实现意图:xunion 序数变化

经过进一步的思考,我们并没有充分考虑上述内容, 语法优势(来源中没有序数)不能弥补:

  • 两种哈希方案,会增加理解 ABI 的含义;
  • 使并集与其同级枚举、位、结构体和表区分开来, 对声明或成员进行重命名

先验技术和参考资料

这些都不是特别相关的。


Footnote1

“联合”是指可扩展联合体,而不是“静态” 接近生命周期结束的工会。

Footnote3

发件人:apang@google.com
收件人:Fibit 用户名单
日期:2019 年 5 月 23 日

FIDLers,您好!在昨天编写测试时,FIDL 团队发现 行为。impl。如果有人声明这一点:

xunion MyXUnion {
    int32 i;  // ordinal might be 0x11111111
}
````

and renames the name of the xunion (not the field), the ordinal of the field
changes:

```fidl
// rename from MyXUnion to MyXUnion2
xunion MyXUnion2 {
    int32 i;  // ordinal now changes to 0x22222222 since the xunion was renamed. d'oh!
}

这可能是意想不到的行为:更改 xunion 的名称 更改 ABI。

改进此功能有两点意义:

  1. 我们想要修改 xunion RFC (RFC-0061),以便派生序数 仅从字段名称中,移除 xunion 名称和从系统提供的 序数哈希计算。
  2. 我们需要更改代码,但遗憾的是,这意味着 xunion ABI 的变化 并可能导致构建不佳幸运的是,我们可以进行一次软过渡 对方法进行哈希处理:让客户端同时检查旧旧版本和新的哈希值,直到 更改会完全滚动整个树

(我们的经验之一是:今后,我们将仔细研究 序数哈希值,以及更改这些内容是否应更改 ABI。)

我们认为这项计划的风险较低 Jeremy 就成功完成了方法序数的软过渡。请 请随时与评论联系,否则我们会尽快开始这项工作。


  1. 奇怪的是,名称对消息的二进制线路格式没有影响 (即位、枚举、结构体、表),但并集除外。因此,在这种情况下, 能够与众不同。