这系列主要是我对WASM研究的笔记,可能内容比较简略。总共包括:
- 深入浅出WebAssembly(1) Compilation
- 深入浅出WebAssembly(2) Basic Api
- 深入浅出WebAssembly(3) Instructions
- 深入浅出WebAssembly(4) Validation
- 深入浅出WebAssembly(5) Memory
- 深入浅出WebAssembly(6) Binary Format
- 深入浅出WebAssembly(7) Future
- 深入浅出WebAssembly(8) Wasm in Rust(TODO)
只有验证通过的模块才能初始化。验证是通过一个在模块ast和内容运行的类型系统(type system)来做的。
Contexts
contexts规定了类型运行的上下文:
- Locals,labels和return type只用在验证函数体内部语句的时候,在其他地方为空。
label
代表的是当前上下文的label stack
用一系列resulttype表示,是当前context中唯一会随着语句顺序执行而变化的部分。 - 具体到实际context,一些空field将会被省略
表示在同样的context C下,将
prepend到C的
field
中- 我们可以使用
这样的索引语法来表示对应索引空间(
index space
)中的内容。而context扩展标记主要用来临时扩展相对索引空间,例如
label indices
。新的语句将在所有现有语句之前定义,占用索引为0的项并将之前的定义的其他项索引加一
Formal Notation
-
Conventions
代表A拥有相应类型T
代表在C这样的上下文中,A拥有相应的类型T
通常一个验证规则可以写成如下形式:
一些规则可以没有前提,称为公理(axiom
),比如i32.add
:
再比如local.get
的规则可以写成:
再比如,前提本身也是一个判断:
Instructions
指令能够通过函数类型来分类。函数类型描述了它怎么操作操作数虚拟机。参数用于push,返回用于pop。如指令
的类型是
,则表示它能够消耗两个
参数,并且产生一个新的。
对于一些指令来说,类型规则并不是严格的类型约束,存在多态:
- 值多态
value-polymorphic
,其中一些值或者操作数是不限定的,比如所有的Parametric instructions
都是(drop,select) - 栈多态
stack-polymorphic
,对栈的状态是不限定的,比如所有控制指令,他们能提供无条件的流程控制。unreachable
,br
,br_table
和return
例如对于select
指令,下面两条语句都是合法的:
另外对于unreachable
指令下的不可到达语句,也要进行类型检查。具体检查方式为:如果存在一个满足当前指令块的栈状态的话那么就合法,否则就不合法:
是合法的,因为当一个栈状态为的时候,
unreachable
的语句能够顺利执行。
是不合法的,因为找不到一个栈能够让这个指令块正常执行。