RFC-0048:显式联合序数 | |
---|---|
状态 | 已接受 |
领域 |
|
说明 | 为了更好地协调可扩展联合(或简单联合)的 ABI 影响,我们提议进行一些更改,使灵活联合在语法上更接近于表格,并纠正目前有关重命名联合或联合成员的奇数 [2] 和过于严格的 ABI 限制。 |
作者 | |
提交日期(年-月-日) | 2019-08-25 |
审核日期(年-月-日) | 2019-09-26 |
摘要
为了更好地对齐可扩展联合(或简称为 union)的 ABI 含义, 提议:
- 将变体成员的语法更改为需要显式序数 (类似于需要表序数)。
- 使用此显式序数,而不是之前实现的经过哈希处理 序数。
- 最后,我们更改传输格式,使并集序数为 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 位显式)序数语法。这个 可以通过以下方式实现:
- 添加 fidlc 形式的检查,以确保 32 位哈希序数的值
始终低于 N。例如,如果 N 为 512,则是哈希序数的十六进制值
必须至少为 0x200。
- 经过哈希处理且小于或等于 <0x200 将导致编译错误,而
字段名称必须使用
[Selector=]
属性手动重命名。我们 请将[Selector]
添加到相应字段中,然后再实现此变更 错别字。 - 鉴于现有哈希架构的随机性,我们预计 错误发生的次数接近于零,因此人工解决方法 。
- 添加此检查可有效地为
[0..N]
显式序数,并确保不会与经过哈希处理的序数发生冲突。
- 经过哈希处理且小于或等于 <0x200 将导致编译错误,而
字段名称必须使用
- 当语言绑定解释序数值时:
<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。
改进此功能有两点意义:
- 我们想要修改 xunion RFC (RFC-0061),以便派生序数 仅从字段名称中,移除 xunion 名称和从系统提供的 序数哈希计算。
- 我们需要更改代码,但遗憾的是,这意味着 xunion ABI 的变化 并可能导致构建不佳幸运的是,我们可以进行一次软过渡 对方法进行哈希处理:让客户端同时检查旧旧版本和新的哈希值,直到 更改会完全滚动整个树
(我们的经验之一是:今后,我们将仔细研究 序数哈希值,以及更改这些内容是否应更改 ABI。)
我们认为这项计划的风险较低 Jeremy 就成功完成了方法序数的软过渡。请 请随时与评论联系,否则我们会尽快开始这项工作。
-
奇怪的是,名称对消息的二进制线路格式没有影响 (即位、枚举、结构体、表),但并集除外。因此,在这种情况下, 能够与众不同。 ↩