RFC-0048:明確的聯集序數 | |
---|---|
狀態 | 已接受 |
區域 |
|
說明 | 為進一步調整可延伸的聯集 (或簡稱為聯集) 的 ABI 影響,我們建議進行變更,讓彈性聯集的語法更接近資料表,並修正目前針對重新命名聯集或聯集成員的奇怪 [2] 且過度嚴格的 ABI 限制。 |
作者 | |
提交日期 (年-月-日) | 2019-08-25 |
審查日期 (年-月-日) | 2019-09-26 |
摘要
為進一步調整可延伸聯集 (或簡稱聯集) 的 ABI 影響,我們建議:
- 變更變數成員的語法,要求明確的序數 (類似於資料表序數的必要性)。
- 請使用這個明確的序數,而非先前實作的雜湊序數。
- 最後,我們會變更線路格式,讓聯集序列為 64 位元 (而非 32 位元)。
這些變更讓彈性聯集在語法上更接近資料表,並修正奇怪的1和過度嚴格的 ABI 限制,以便重新命名聯集或聯集成員。
動機與設計
除了聯集之外,名稱對類型沒有任何 ABI 影響:您可以重新命名枚舉、位元、結構體和資料表,或讓成員重新命名,而不用擔心二進位相容性。由於我們選擇使用以雜湊為基礎的技術來指派變化序數 (請參閱 RFC-0061:可擴充的聯集),因此聯集有所不同。
我們已瞭解這個缺點,並提出解決方法:請參閱「Intent to implement: xunion ordinals change」,其中建議變更雜湊演算法,只包含成員名稱。
相反地,這項提案更進一步,只使用明確的序數,因此可避免名稱與 ABI 相容性之間的任何關聯。我們認為在聯集宣告中寫入序數的額外工作量不大:目前表格中的明確序數並未造成問題,而且其他熱門 IDL 也有很多以編號命名成員或變體的先例。
此外,為了進一步與資料表保持一致,我們要求從 1 開始依序指派序數,並允許使用關鍵字 reserved
明確略過聯集變數。
僅對通訊協定進行雜湊運算
與類型不同,通訊協定會使用以雜湊為基礎的方法來指派序數。這項功能的動機來自兩個主要用途:
- 通訊協定可組合,因此我們需要全域序號指派配置,以免發生距離問題。請參閱 [RFC-0063: OrdinalRangeOrdinalRange、RFC-0020: Interface Ordinal Hashing 和 RFC-0029: Increasing Method Ordinals。
- 實際上,全域不重複 ID 可大幅簡化並強化監控和追蹤等需求,例如 fidlcat 需要能夠明確識別方法叫用。
這些用途無法轉換為類型。
這項提案的效果是,只有通訊協定會使用雜湊。只有一個雜湊演算法,即 RFC-0029 中所述的演算法。
64 位元序號是標準
目前,在 union 內嵌內容中,有 4 個位元組的填充:
- 序數 (
uint32
) - 邊框間距 (
uint32
) - 信封 (16 個位元組)
相反地,我們希望所有位元組都以明確的格式呼叫,因此將序號變更為 64b。一般來說,我們偏好無填充結構,因為這類結構的效率較高 (例如,不需要明確的 memset 或額外的編碼表)。
如要瞭解如何以軟性方式轉換至 64 位元序號,請參閱「實作策略」一節。
JSON 線路格式
我們先前曾討論過,在建立 JSON 匯入格式時,類型和成員的重新命名會對該格式中的 ABI 造成影響。
依據「線路格式」分開 ABI 損壞情形相當實用。我們可以從不同的屬性取得不同的屬性。在所有支援的可能通訊格式中,只有少數訊息需要在 ABI 相容性方面進行調整,因此這類訊息的演進方式將受到嚴格限制。其他人則應盡可能採用更具彈性的規則。
預做準備:稀疏資料表
我們曾討論過支援稀疏資料表,也就是除了結構和資料表之外,第三種記錄類資料的版面配置。如果我們決定推出這第三個選項,假設的語法會遵循這項提案,以及目前的資料表語法:
sparse_table Example {
1: T1 field1;
2: reserved; // deprecated
3: T3 field3;
};
導入策略
如要啟用軟性轉換,我們需要在傳統 (32 位元雜湊) 序數語法和建議的 (64 位元明確) 序數語法之間做出區別。您可以透過下列方式執行這項操作:
- 在 fidlc 中新增檢查項目,確保 32 位元雜湊序數的值絕不會低於 N。舉例來說,如果 N 為 512,則雜湊序數的 16 進位值至少必須為 0x200。
- 哈希序數小於 0x200 會導致編譯錯誤,而且欄位名稱必須使用
[Selector=]
屬性手動重新命名。我們會在 fidlc 中實施這項變更前,先在適當的欄位中加入[Selector]
。 - 考量現有雜湊演算法的隨機性,我們預期雜湊錯誤發生的次數幾乎為零,因此可能不需要手動解決。
- 加入這項檢查可有效地為明確的序數分配
[0..N]
序數空間,並確保不會與雜湊序數衝突。
- 哈希序數小於 0x200 會導致編譯錯誤,而且欄位名稱必須使用
- 當語言繫結解讀序數值時:
- 如果序數介於
[0, N)
之間,則序數為 64 位元且為明確序數。 - 如果序數介於
[N, UINT32_MAX]
之間,則序數為 32 位元並經過雜湊。 - 如果序數介於
[UINT32_MAX, UINT64_MAX)
之間,繫結務必會觸發錯誤,並關閉含有碑文的管道。
- 如果序數介於
人體工學
讓 ABI 人體工學變得更加簡單,只需使用明確的序數,就能降低語法成本。
說明文件和範例
至少:
回溯相容性
未明確使用序列語法的聯集會繼續使用現有的 32 位元雜湊序列方案。因此,現有的聯合會繼續與 API 和 ABI 相容。
使用明確的序數語法定義的聯集會使用本 RFC 中所述的 64 位元序數配置。如要瞭解如何同時支援 32 位元和 64 位元序號架構,請參閱「實作策略」一節。
成效
極為微小的改善:由於 switch() 陳述式的 codegen 更佳,因此這個配置比雜湊序數更有效率。
安全性
沒有影響。
測試
一如往常,瑣事一堆。
缺點、替代方案和未知事項
替代做法:僅對成員名稱進行序數雜湊
請參閱「Intent to implement:xunion 序數變更」。
經過進一步思考,我們認為上述做法不足以彌補缺點,因為語法優勢 (來源中沒有序數) 無法彌補缺點:
- 兩種雜湊演算法,讓人難以瞭解 ABI 的影響。
- 在重新命名宣告或成員時,讓並集與其兄弟姐妹列舉、位元、結構體和資料表保持區別。
既有技術與參考資料
沒有特別相關的內容。
Footnote1
本文中的「聯集」是指可擴充的聯集,而非即將淘汰的「靜態」聯集。
Footnote3
寄件者:apang@google.com
收件者:fidl 使用者名單
日期:2019 年 5 月 23 日
各位 FIDL 使用者,你好!昨天撰寫測試時,FIDL 團隊發現目前的 xunion 規格和實作項目有令人意外的行為。如果宣告以下內容:
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 變更,進而導致建構失敗。幸好,我們可以透過 Jeremy Manson 首創的技術,為方法實作序列雜湊,讓客戶同時檢查舊版和新版雜湊,直到變更完全在樹狀結構中推送為止。
(所學到的一課:日後我們應仔細查看序數雜湊包含哪些內容,以及變更這些內容是否應變更 ABI)。
我們認為這項計畫風險較低,因為可以進行軟性轉換,而 Jeremy 也已成功為方法序號執行這項作業。請提供意見,否則我們很快就會著手處理這項工作。
-
這點很奇怪,因為除了聯集之外,名稱不會影響訊息的二進位線格式 (即位元、列舉、結構體、表格)。因此,這類情況與其他情況不同。 ↩