Skip to content

Latest commit

 

History

History
74 lines (45 loc) · 7.88 KB

GC.md

File metadata and controls

74 lines (45 loc) · 7.88 KB

GC/DOM/Web API 集成 [:Unicorn:][未来通用]

注意:这是一个 [未来:unicorn:][未来通用] 功能!##

之后MVP,为了实现高层次目标(1)与现有 Web 平台良好集成以及(2)支持 C++ 以外的语言,WebAssembly 需要能够:

  • 直接从 WebAssembly 代码引用 DOM 和其他 Web API 对象;
  • 直接从 WebAssembly 调用 Web API(传递原语或 DOM/GC/Web API 对象),而无需通过 JavaScript 调用;和
  • 直接从 WebAssembly 代码高效地分配和操作 GC 对象。

以下文档是实现上述目标的一种方法的高级概述。认为内容不完整,并预计随着时间的推移会发生变化。

一个重要的约束是,虽然 WebAssembly 应该允许与Web紧密集成,但它不应该包含阻止在中非 Web 嵌入执行的细节或 Web 标准依赖项。这暗示了一种设计(下面称为不透明引用类型),它将 JavaScript 和 WebIDL 的细节隐藏在特定于 Web 嵌入的内置模块后面。另一方面,WebAssembly 可以定义一组native GC原语,允许编写可移植的 GC 代码,而不受主机环境的影响。

不透明引用类型

第一个功能是扩展模块导入以允许模块导入不透明引用类型。“不透明”意味着引用类型本身没有结构内容,并且例如不定义任何方法或字段。导入后,可以在其他导入函数的签名中使用不透明引用类型。因此,不透明引用类型的点将被传递给导出函数并从导出函数返回。

允许将引用类型用作局部变量、参数和返回类型的类型。此外,允许将引用作为运算符的操作数,这些运算符将其值视为黑盒( brblock 等)。将添加一个新 dynamic_cast 的操作符,以允许从任何不透明引用类型到任何其他不透明引用类型的检查转换。强制转换是否成功取决于主机环境。WebAssembly 本身不会定义先验子类型关系。

出于安全和限制不确定性的原因,导入的不透明引用类型将不能从线性内存中加载或存储到线性内存中,否则它们将被任意别名为整数。相反,将添加一组新的操作符,用于从整数索引单元中分配、释放、加载和存储,这些单元可以保存引用,并且不能被线性内存别名。

使用表示为导入的不透明引用类型,宿主环境可以通过内置模块提供对各种引用计数或垃圾收集的宿主定义对象的访问。虽然这种设计并不强制要求使用 JavaScript VM 或浏览器,但它确实允许与JavaScriptWebIDL在 Web 环境中自然集成。

JavaScript 集成

使用不透明引用类型,WebAssembly 代码可以通过内置模块访问 JavaScript 值,该 js 内置模块提供:

  • 导出 string 不透明引用类型和导出函数,以分配、查询长度和索引值 string
  • 与 ES5 元对象协议相对应的导出 object 的不透明引用类型和导出的函数,包括函数对象的能力 [[Call]]
  • 进一步导出符号和值类型的不透明引用类型(包括 SIMD);
  • 导出 value 的不透明引用类型,具有用于从整数、浮点数、 object s、 string s 等构造 value s 的导出函数,以及用于查询 a value 的类型和提取上述有效负载类型的导出函数。

由于浏览器的 WebAssembly 引擎完全了解 js 内置模块,因此它应该能够优化字符串/对象访问以及普通的 JavaScript JIT 编译器(甚至可能使用相同的 JIT 编译器)。

WebIDL 集成

使用不透明引用类型,通过将 DOM 和 Web API 的WebIDL接口映射到 WebAssembly 内置模块签名,可以允许直接访问 DOM 和 Web API.特别是:

这个高层次的描述掩盖了关于 WebIDL 的许多重要细节:

首先,WebIDL 规范包含许多特定于 JavaScript 的细节,这些细节在 WebAssembly 上下文中是不必要的。特别是,WebIDL 接口基本上指定了三个组件:

  1. 由独立于语言的数据类型(如 IEEE754 双精度和浮点数)组成的签名声明;
  2. 对(1)中声明的签名的自变量执行的一组基本格式良好性检查;和
  3. 一种特定于 JavaScript 的算法,它将传递给 WebIDL 调用的任意一组 JavaScript 值映射到由(1)声明并由(2)检查的签名。

WebIDL 规范的(1)和(2)对 WebAssembly 有意义,但(3)将被有效地跳过。

另一个重要的问题是将 WebIDL 值映射为不简单原始类型的类型:

  • 字典类型appear需要 JavaScript 对象,但实际上被定义为值,以便它们可以(并且在各种浏览器实现中)展平为 C 结构。因此,自然的 WebAssembly 绑定是将字典映射到通过引用(整数偏移量)传递的线性内存中的结构。
  • 同样适用于序列类型
  • 枚举类型可以映射到规范整数。
  • 联合类型可以用多种方式处理。一种选择是将联合类型本身视为可导入的不透明引用类型(当所有元素本身都是引用类型时)。另一种选择是为联合类型的每个元素引入每个签名的重载,以便所有调用都传递单个元素类型,并且完整的联合类型永远不会在 WebAssembly 中显式表示。
  • 回调函数类型可以映射到 (function pointer, environment pointer) 闭包对。

总的来说,将 WebIDL 映射到 WebAssembly 内置模块的目标是避免为所有 Web API 定义重复的 WebAssembly 接口。在实践中,一些 WebIDL 模式可能具有不自然或低效的 WebAssembly 映射,因此需要采用新的重载和最佳实践。然而,随着时间的推移,这些粗糙的边缘将被消除,留下使用单一接口定义 Web API 的长期利益,并确保 JavaScript 和 WebAssembly 始终可以访问相同的原始功能。

原生 GC

不透明的引用类型相比,第二个特性是允许通过非不透明引用类型从 WebAssembly 代码直接进行 GC 分配和字段访问。

对于此功能,还有许多设计需要考虑,但有几点暂时达成了一致:

  • 为了避免在单一语言的对象模型中进行烘焙,请定义低级 GC 原语(即,结构和数组),并允许源语言编译器构建虚拟调度和访问控制等功能。
  • GC 结构和数组类型将与类似且对称的不透明引用类型(不是不透明的)关联结构/数组引用类型
  • GC 堆在语义上不同于线性内存,因此 GC 对象的字段可以安全地保存引用类型(与线性内存不同)。
  • 通过使用类型化对象建议在 JavaScript 中反射 WebAssembly GC 对象,可以将 GC 结构和数组类型传递到 JavaScript 或从 JavaScript 传递。