模块¶
对于模块,执行语义主要定义实例化,它分配模块及其包含定义的实例,从包含的表和内存初始化元素和数据段,并在存在时调用启动函数。它还包括导出函数的调用。
外部类型¶
为了根据导入检查外部值,这些值通过外部类型进行分类。以下辅助类型规则相对于存储\(S\)指定此类型关系,其中引用的实例位于其中。
\(\href{../exec/runtime.html#syntax-externval}{\mathsf{func}}~a\)¶
存储条目\(S.\href{../exec/runtime.html#syntax-store}{\mathsf{funcs}}[a]\)必须存在。
然后\(\href{../exec/runtime.html#syntax-externval}{\mathsf{func}}~a\)与外部类型\(\href{../syntax/types.html#syntax-externtype}{\mathsf{func}}~S.\href{../exec/runtime.html#syntax-store}{\mathsf{funcs}}[a].\href{../exec/runtime.html#syntax-funcinst}{\mathsf{type}}\)有效。
\(\href{../exec/runtime.html#syntax-externval}{\mathsf{table}}~a\)¶
存储条目\(S.\href{../exec/runtime.html#syntax-store}{\mathsf{tables}}[a]\)必须存在。
然后\(\href{../exec/runtime.html#syntax-externval}{\mathsf{table}}~a\)与外部类型\(\href{../syntax/types.html#syntax-externtype}{\mathsf{table}}~S.\href{../exec/runtime.html#syntax-store}{\mathsf{tables}}[a].\href{../exec/runtime.html#syntax-tableinst}{\mathsf{type}}\)有效。
\(\href{../exec/runtime.html#syntax-externval}{\mathsf{mem}}~a\)¶
存储条目\(S.\href{../exec/runtime.html#syntax-store}{\mathsf{mems}}[a]\)必须存在。
然后\(\href{../exec/runtime.html#syntax-externval}{\mathsf{mem}}~a\)与外部类型\(\href{../syntax/types.html#syntax-externtype}{\mathsf{mem}}~S.\href{../exec/runtime.html#syntax-store}{\mathsf{mems}}[a].\href{../exec/runtime.html#syntax-meminst}{\mathsf{type}}\)有效。
\(\href{../exec/runtime.html#syntax-externval}{\mathsf{global}}~a\)¶
存储条目\(S.\href{../exec/runtime.html#syntax-store}{\mathsf{globals}}[a]\)必须存在。
然后\(\href{../exec/runtime.html#syntax-externval}{\mathsf{global}}~a\)与外部类型\(\href{../syntax/types.html#syntax-externtype}{\mathsf{global}}~S.\href{../exec/runtime.html#syntax-store}{\mathsf{globals}}[a].\href{../exec/runtime.html#syntax-globalinst}{\mathsf{type}}\)有效。
值类型¶
为了根据导出函数的参数类型检查参数值,值通过值类型进行分类。以下辅助类型规则相对于存储\(S\)指定此类型关系,其中可能引用的地址位于其中。
数值 \(t.\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{const}}~c\)¶
该值与数值类型\(t\)有效。
空引用 \(\href{../syntax/instructions.html#syntax-instr-ref}{\mathsf{ref{.}null}}~t\)¶
该值与引用类型\(t\)有效。
函数引用 \(\href{../exec/runtime.html#syntax-ref}{\mathsf{ref}}~a\)¶
外部值\(\href{../exec/runtime.html#syntax-externval}{\mathsf{func}}~a\)必须有效。
然后该值与引用类型\(\href{../syntax/types.html#syntax-reftype}{\mathsf{funcref}}\)有效。
外部引用 \(\href{../exec/runtime.html#syntax-ref.extern}{\mathsf{ref{.}extern}}~a\)¶
该值与引用类型\(\href{../syntax/types.html#syntax-reftype}{\mathsf{externref}}\)有效。
分配¶
在存储\(S\)中分配函数、表、内存和全局变量的新实例,如下面的辅助函数所定义。
函数¶
令\(\href{../syntax/modules.html#syntax-func}{\mathit{func}}\)为要分配的函数,\(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}\)为其模块实例。
令\(a\)为\(S\)中第一个空闲的函数地址。
令\(\href{../syntax/types.html#syntax-functype}{\mathit{functype}}\)为函数类型\(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}.\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{types}}[\href{../syntax/modules.html#syntax-func}{\mathit{func}}.\href{../syntax/modules.html#syntax-func}{\mathsf{type}}]\)。
令\(\href{../exec/runtime.html#syntax-funcinst}{\mathit{funcinst}}\)为函数实例\(\{ \href{../exec/runtime.html#syntax-funcinst}{\mathsf{type}}~\href{../syntax/types.html#syntax-functype}{\mathit{functype}}, \href{../exec/runtime.html#syntax-funcinst}{\mathsf{module}}~\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}, \href{../exec/runtime.html#syntax-funcinst}{\mathsf{code}}~\href{../syntax/modules.html#syntax-func}{\mathit{func}} \}\)。
将\(\href{../exec/runtime.html#syntax-funcinst}{\mathit{funcinst}}\)追加到\(S\)的\(\href{../exec/runtime.html#syntax-store}{\mathsf{funcs}}\)中。
返回\(a\)。
主机函数¶
令 \(\href{../exec/runtime.html#syntax-hostfunc}{\mathit{hostfunc}}\) 为用于分配的主机函数,并令 \(\href{../syntax/types.html#syntax-functype}{\mathit{functype}}\) 为其函数类型。
令\(a\)为\(S\)中第一个空闲的函数地址。
令 \(\href{../exec/runtime.html#syntax-funcinst}{\mathit{funcinst}}\) 为函数实例 \(\{ \href{../exec/runtime.html#syntax-funcinst}{\mathsf{type}}~\href{../syntax/types.html#syntax-functype}{\mathit{functype}}, \href{../exec/runtime.html#syntax-funcinst}{\mathsf{hostcode}}~\href{../exec/runtime.html#syntax-hostfunc}{\mathit{hostfunc}} \}\)。
将\(\href{../exec/runtime.html#syntax-funcinst}{\mathit{funcinst}}\)追加到\(S\)的\(\href{../exec/runtime.html#syntax-store}{\mathsf{funcs}}\)中。
返回\(a\)。
注意
主机函数永远不会由 WebAssembly 语义本身分配,但可能由嵌入器分配。
表格¶
令 \(\href{../syntax/types.html#syntax-tabletype}{\mathit{tabletype}}\) 为要分配的表格类型,并令 \(\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}\) 为初始化值。
令 \((\{\href{../syntax/types.html#syntax-limits}{\mathsf{min}}~n, \href{../syntax/types.html#syntax-limits}{\mathsf{max}}~m^?\}~\href{../syntax/types.html#syntax-reftype}{\mathit{reftype}})\) 为表格类型 \(\href{../syntax/types.html#syntax-tabletype}{\mathit{tabletype}}\) 的结构。
令 \(a\) 为 \(S\) 中第一个空闲的表格地址。
令 \(\href{../exec/runtime.html#syntax-tableinst}{\mathit{tableinst}}\) 为表格实例 \(\{ \href{../exec/runtime.html#syntax-tableinst}{\mathsf{type}}~\href{../syntax/types.html#syntax-tabletype}{\mathit{tabletype}}, \href{../exec/runtime.html#syntax-tableinst}{\mathsf{elem}}~\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}^n \}\),其中有 \(n\) 个元素设置为 \(\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}\)。
将 \(\href{../exec/runtime.html#syntax-tableinst}{\mathit{tableinst}}\) 附加到 \(S\) 的 \(\href{../exec/runtime.html#syntax-store}{\mathsf{tables}}\) 中。
返回\(a\)。
内存¶
令 \(\href{../syntax/types.html#syntax-memtype}{\mathit{memtype}}\) 为要分配的内存类型。
令 \(\{\href{../syntax/types.html#syntax-limits}{\mathsf{min}}~n, \href{../syntax/types.html#syntax-limits}{\mathsf{max}}~m^?\}\) 为内存类型 \(\href{../syntax/types.html#syntax-memtype}{\mathit{memtype}}\) 的结构。
令 \(a\) 为 \(S\) 中第一个空闲的内存地址。
令 \(\href{../exec/runtime.html#syntax-meminst}{\mathit{meminst}}\) 为内存实例 \(\{ \href{../exec/runtime.html#syntax-meminst}{\mathsf{type}}~\href{../syntax/types.html#syntax-memtype}{\mathit{memtype}}, \href{../exec/runtime.html#syntax-meminst}{\mathsf{data}}~(\def\mathdef2203#1{\mathtt{0x#1}}\mathdef2203{00})^{n \cdot 64\,\mathrm{Ki}} \}\),它包含 \(n\) 页清零的字节。
将 \(\href{../exec/runtime.html#syntax-meminst}{\mathit{meminst}}\) 附加到 \(S\) 的 \(\href{../exec/runtime.html#syntax-store}{\mathsf{mems}}\) 中。
返回\(a\)。
全局变量¶
令 \(\href{../syntax/types.html#syntax-globaltype}{\mathit{globaltype}}\) 为要分配的全局变量类型,并令 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}\) 为用于初始化全局变量的值。
令 \(a\) 为 \(S\) 中第一个空闲的全局变量地址。
令 \(\href{../exec/runtime.html#syntax-globalinst}{\mathit{globalinst}}\) 为全局变量实例 \(\{ \href{../exec/runtime.html#syntax-globalinst}{\mathsf{type}}~\href{../syntax/types.html#syntax-globaltype}{\mathit{globaltype}}, \href{../exec/runtime.html#syntax-globalinst}{\mathsf{value}}~\href{../exec/runtime.html#syntax-val}{\mathit{val}} \}\)。
将 \(\href{../exec/runtime.html#syntax-globalinst}{\mathit{globalinst}}\) 附加到 \(S\) 的 \(\href{../exec/runtime.html#syntax-store}{\mathsf{globals}}\) 中。
返回\(a\)。
元素段¶
令 \(\href{../syntax/types.html#syntax-reftype}{\mathit{reftype}}\) 为元素的类型,并令 \(\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}^\ast\) 为要分配的引用 向量。
令 \(a\) 为 \(S\) 中第一个空闲的元素地址。
令 \(\href{../exec/runtime.html#syntax-eleminst}{\mathit{eleminst}}\) 为元素实例 \(\{ \href{../exec/runtime.html#syntax-eleminst}{\mathsf{type}}~\href{../syntax/types.html#syntax-reftype}{\mathit{reftype}}, \href{../exec/runtime.html#syntax-eleminst}{\mathsf{elem}}~\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}^\ast \}\)。
将 \(\href{../exec/runtime.html#syntax-eleminst}{\mathit{eleminst}}\) 附加到 \(S\) 的 \(\href{../exec/runtime.html#syntax-store}{\mathsf{elems}}\) 中。
返回\(a\)。
数据段¶
令 \(b^\ast\) 为要分配的字节 向量。
令 \(a\) 为 \(S\) 中第一个空闲的数据地址。
令 \(\href{../exec/runtime.html#syntax-datainst}{\mathit{datainst}}\) 为数据实例 \(\{ \href{../exec/runtime.html#syntax-datainst}{\mathsf{data}}~b^\ast \}\)。
将 \(\href{../exec/runtime.html#syntax-datainst}{\mathit{datainst}}\) 附加到 \(S\) 的 \(\href{../exec/runtime.html#syntax-store}{\mathsf{datas}}\) 中。
返回\(a\)。
增长表¶
令\(\href{../exec/runtime.html#syntax-tableinst}{\mathit{tableinst}}\) 为要增长的表实例,\(n\) 为要增长的元素数量,\(\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}\) 为初始化值。
令\(\mathit{len}\) 为 \(n\) 加上 \(\href{../exec/runtime.html#syntax-tableinst}{\mathit{tableinst}}.\href{../exec/runtime.html#syntax-tableinst}{\mathsf{elem}}\) 的长度。
如果\(\mathit{len}\) 大于或等于 \(2^{32}\),则失败。
令\(\href{../syntax/types.html#syntax-limits}{\mathit{limits}}~t\) 为表类型 \(\href{../exec/runtime.html#syntax-tableinst}{\mathit{tableinst}}.\href{../exec/runtime.html#syntax-tableinst}{\mathsf{type}}\) 的结构。
令\(\href{../syntax/types.html#syntax-limits}{\mathit{limits}}'\) 为 \(\href{../syntax/types.html#syntax-limits}{\mathit{limits}}\),其中 \(\href{../syntax/types.html#syntax-limits}{\mathsf{min}}\) 更新为 \(\mathit{len}\)。
如果\(\href{../syntax/types.html#syntax-limits}{\mathit{limits}}'\) 不是有效的,则失败。
将 \(\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}^n\) 附加到 \(\href{../exec/runtime.html#syntax-tableinst}{\mathit{tableinst}}.\href{../exec/runtime.html#syntax-tableinst}{\mathsf{elem}}\)。
将 \(\href{../exec/runtime.html#syntax-tableinst}{\mathit{tableinst}}.\href{../exec/runtime.html#syntax-tableinst}{\mathsf{type}}\) 设置为表类型 \(\href{../syntax/types.html#syntax-limits}{\mathit{limits}}'~t\)。
增长内存¶
令\(\href{../exec/runtime.html#syntax-meminst}{\mathit{meminst}}\) 为要增长的内存实例,\(n\) 为要增长的页面 数量。
断言:\(\href{../exec/runtime.html#syntax-meminst}{\mathit{meminst}}.\href{../exec/runtime.html#syntax-meminst}{\mathsf{data}}\) 的长度可以被页面大小 \(64\,\mathrm{Ki}\) 整除。
令\(\mathit{len}\) 为 \(n\) 加上 \(\href{../exec/runtime.html#syntax-meminst}{\mathit{meminst}}.\href{../exec/runtime.html#syntax-meminst}{\mathsf{data}}\) 的长度除以页面大小 \(64\,\mathrm{Ki}\)。
如果\(\mathit{len}\) 大于 \(2^{16}\),则失败。
令\(\href{../syntax/types.html#syntax-limits}{\mathit{limits}}\) 为内存类型 \(\href{../exec/runtime.html#syntax-meminst}{\mathit{meminst}}.\href{../exec/runtime.html#syntax-meminst}{\mathsf{type}}\) 的结构。
令\(\href{../syntax/types.html#syntax-limits}{\mathit{limits}}'\) 为 \(\href{../syntax/types.html#syntax-limits}{\mathit{limits}}\),其中 \(\href{../syntax/types.html#syntax-limits}{\mathsf{min}}\) 更新为 \(\mathit{len}\)。
如果\(\href{../syntax/types.html#syntax-limits}{\mathit{limits}}'\) 不是有效的,则失败。
将 \(n\) 次 \(64\,\mathrm{Ki}\) 字节(值为 \(\def\mathdef2205#1{\mathtt{0x#1}}\mathdef2205{00}\))附加到 \(\href{../exec/runtime.html#syntax-meminst}{\mathit{meminst}}.\href{../exec/runtime.html#syntax-meminst}{\mathsf{data}}\)。
将 \(\href{../exec/runtime.html#syntax-meminst}{\mathit{meminst}}.\href{../exec/runtime.html#syntax-meminst}{\mathsf{type}}\) 设置为内存类型 \(\href{../syntax/types.html#syntax-limits}{\mathit{limits}}'\)。
模块¶
模块的分配函数需要一个合适的外部值列表,这些值假定与模块的导入向量匹配,一个模块的全局变量的初始化值列表,以及模块的元素段的引用向量列表。
令\(\href{../syntax/modules.html#syntax-module}{\mathit{module}}\) 为要分配的模块,\(\href{../exec/runtime.html#syntax-externval}{\mathit{externval}}_{\mathrm{im}}^\ast\) 为提供模块导入的外部值向量,\(\href{../exec/runtime.html#syntax-val}{\mathit{val}}^\ast\) 为模块全局变量的初始化值,\((\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}^\ast)^\ast\) 为模块元素段的引用向量。
对于 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}.\href{../syntax/modules.html#syntax-module}{\mathsf{funcs}}\) 中的每个函数 \(\href{../syntax/modules.html#syntax-func}{\mathit{func}}_i\),执行以下操作
对于 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}.\href{../syntax/modules.html#syntax-module}{\mathsf{tables}}\) 中的每个表 \(\href{../syntax/modules.html#syntax-table}{\mathit{table}}_i\),执行以下操作
令\(\href{../syntax/types.html#syntax-limits}{\mathit{limits}}_i~t_i\) 为表类型 \(\href{../syntax/modules.html#syntax-table}{\mathit{table}}_i.\href{../syntax/modules.html#syntax-table}{\mathsf{type}}\)。
令\(\href{../exec/runtime.html#syntax-tableaddr}{\mathit{tableaddr}}_i\) 为从分配 \(\href{../syntax/modules.html#syntax-table}{\mathit{table}}_i.\href{../syntax/modules.html#syntax-table}{\mathsf{type}}\)(初始化值为 \(\href{../syntax/instructions.html#syntax-instr-ref}{\mathsf{ref{.}null}}~t_i\))得到的表地址。
对于 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}.\href{../syntax/modules.html#syntax-module}{\mathsf{mems}}\) 中的每个内存 \(\href{../syntax/modules.html#syntax-mem}{\mathit{mem}}_i\),执行以下操作
对于 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}.\href{../syntax/modules.html#syntax-module}{\mathsf{globals}}\) 中的每个全局变量 \(\href{../syntax/modules.html#syntax-global}{\mathit{global}}_i\),执行以下操作
对于模块 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}.\href{../syntax/modules.html#syntax-module}{\mathsf{elems}}\) 中的每个 元素段 \(\href{../syntax/modules.html#syntax-elem}{\mathit{elem}}_i\),执行以下操作
令 \(\href{../exec/runtime.html#syntax-elemaddr}{\mathit{elemaddr}}_i\) 为通过 分配 一个 引用类型 \(\href{../syntax/modules.html#syntax-elem}{\mathit{elem}}_i.\href{../syntax/modules.html#syntax-elem}{\mathsf{type}}\) 的 元素实例(其内容为 \((\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}^\ast)^\ast[i]\))而得到的 元素地址。
对于模块 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}.\href{../syntax/modules.html#syntax-module}{\mathsf{datas}}\) 中的每个 数据段 \(\href{../syntax/modules.html#syntax-data}{\mathit{data}}_i\),执行以下操作
令 \(\href{../exec/runtime.html#syntax-funcaddr}{\mathit{funcaddr}}^\ast\) 为按索引顺序连接的 函数地址 \(\href{../exec/runtime.html#syntax-funcaddr}{\mathit{funcaddr}}_i\)。
令 \(\href{../exec/runtime.html#syntax-tableaddr}{\mathit{tableaddr}}^\ast\) 为按索引顺序连接的 表地址 \(\href{../exec/runtime.html#syntax-tableaddr}{\mathit{tableaddr}}_i\)。
令 \(\href{../exec/runtime.html#syntax-memaddr}{\mathit{memaddr}}^\ast\) 为按索引顺序连接的 内存地址 \(\href{../exec/runtime.html#syntax-memaddr}{\mathit{memaddr}}_i\)。
令 \(\href{../exec/runtime.html#syntax-globaladdr}{\mathit{globaladdr}}^\ast\) 为按索引顺序连接的 全局地址 \(\href{../exec/runtime.html#syntax-globaladdr}{\mathit{globaladdr}}_i\)。
令 \(\href{../exec/runtime.html#syntax-elemaddr}{\mathit{elemaddr}}^\ast\) 为按索引顺序连接的 元素地址 \(\href{../exec/runtime.html#syntax-elemaddr}{\mathit{elemaddr}}_i\)。
令 \(\href{../exec/runtime.html#syntax-dataaddr}{\mathit{dataaddr}}^\ast\) 为按索引顺序连接的 数据地址 \(\href{../exec/runtime.html#syntax-dataaddr}{\mathit{dataaddr}}_i\)。
令 \(\href{../exec/runtime.html#syntax-funcaddr}{\mathit{funcaddr}}_{\mathrm{mod}}^\ast\) 为从 \(\href{../exec/runtime.html#syntax-externval}{\mathit{externval}}_{\mathrm{im}}^\ast\) 中提取的 函数地址 列表,与 \(\href{../exec/runtime.html#syntax-funcaddr}{\mathit{funcaddr}}^\ast\) 连接。
令 \(\href{../exec/runtime.html#syntax-tableaddr}{\mathit{tableaddr}}_{\mathrm{mod}}^\ast\) 为从 \(\href{../exec/runtime.html#syntax-externval}{\mathit{externval}}_{\mathrm{im}}^\ast\) 中提取的 表地址 列表,与 \(\href{../exec/runtime.html#syntax-tableaddr}{\mathit{tableaddr}}^\ast\) 连接。
令 \(\href{../exec/runtime.html#syntax-memaddr}{\mathit{memaddr}}_{\mathrm{mod}}^\ast\) 为从 \(\href{../exec/runtime.html#syntax-externval}{\mathit{externval}}_{\mathrm{im}}^\ast\) 中提取的 内存地址 列表,与 \(\href{../exec/runtime.html#syntax-memaddr}{\mathit{memaddr}}^\ast\) 连接。
令 \(\href{../exec/runtime.html#syntax-globaladdr}{\mathit{globaladdr}}_{\mathrm{mod}}^\ast\) 为从 \(\href{../exec/runtime.html#syntax-externval}{\mathit{externval}}_{\mathrm{im}}^\ast\) 中提取的 全局地址 列表,与 \(\href{../exec/runtime.html#syntax-globaladdr}{\mathit{globaladdr}}^\ast\) 连接。
对于模块 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}.\href{../syntax/modules.html#syntax-module}{\mathsf{exports}}\) 中的每个 导出 \(\href{../syntax/modules.html#syntax-export}{\mathit{export}}_i\),执行以下操作
如果 \(\href{../syntax/modules.html#syntax-export}{\mathit{export}}_i\) 是 函数索引 \(x\) 的函数导出,则令 \(\href{../exec/runtime.html#syntax-externval}{\mathit{externval}}_i\) 为 外部值 \(\href{../exec/runtime.html#syntax-externval}{\mathsf{func}}~(\href{../exec/runtime.html#syntax-funcaddr}{\mathit{funcaddr}}_{\mathrm{mod}}^\ast[x])\)。
否则,如果 \(\href{../syntax/modules.html#syntax-export}{\mathit{export}}_i\) 是 表索引 \(x\) 的表导出,则令 \(\href{../exec/runtime.html#syntax-externval}{\mathit{externval}}_i\) 为 外部值 \(\href{../exec/runtime.html#syntax-externval}{\mathsf{table}}~(\href{../exec/runtime.html#syntax-tableaddr}{\mathit{tableaddr}}_{\mathrm{mod}}^\ast[x])\)。
否则,如果 \(\href{../syntax/modules.html#syntax-export}{\mathit{export}}_i\) 是 内存索引 \(x\) 的内存导出,则令 \(\href{../exec/runtime.html#syntax-externval}{\mathit{externval}}_i\) 为 外部值 \(\href{../exec/runtime.html#syntax-externval}{\mathsf{mem}}~(\href{../exec/runtime.html#syntax-memaddr}{\mathit{memaddr}}_{\mathrm{mod}}^\ast[x])\)。
否则,如果 \(\href{../syntax/modules.html#syntax-export}{\mathit{export}}_i\) 是 全局索引 \(x\) 的全局导出,则令 \(\href{../exec/runtime.html#syntax-externval}{\mathit{externval}}_i\) 为 外部值 \(\href{../exec/runtime.html#syntax-externval}{\mathsf{global}}~(\href{../exec/runtime.html#syntax-globaladdr}{\mathit{globaladdr}}_{\mathrm{mod}}^\ast[x])\)。
令 \(\href{../exec/runtime.html#syntax-exportinst}{\mathit{exportinst}}_i\) 为 导出实例 \(\{\href{../exec/runtime.html#syntax-exportinst}{\mathsf{name}}~(\href{../syntax/modules.html#syntax-export}{\mathit{export}}_i.\href{../syntax/modules.html#syntax-export}{\mathsf{name}}), \href{../exec/runtime.html#syntax-exportinst}{\mathsf{value}}~\href{../exec/runtime.html#syntax-externval}{\mathit{externval}}_i\}\)。
令 \(\href{../exec/runtime.html#syntax-exportinst}{\mathit{exportinst}}^\ast\) 为按索引顺序连接的 导出实例 \(\href{../exec/runtime.html#syntax-exportinst}{\mathit{exportinst}}_i\)。
令 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}\) 为 模块实例 \(\{\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{types}}~(\href{../syntax/modules.html#syntax-module}{\mathit{module}}.\href{../syntax/modules.html#syntax-module}{\mathsf{types}}),\) \(\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{funcaddrs}}~\href{../exec/runtime.html#syntax-funcaddr}{\mathit{funcaddr}}_{\mathrm{mod}}^\ast,\) \(\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{tableaddrs}}~\href{../exec/runtime.html#syntax-tableaddr}{\mathit{tableaddr}}_{\mathrm{mod}}^\ast,\) \(\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{memaddrs}}~\href{../exec/runtime.html#syntax-memaddr}{\mathit{memaddr}}_{\mathrm{mod}}^\ast,\) \(\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{globaladdrs}}~\href{../exec/runtime.html#syntax-globaladdr}{\mathit{globaladdr}}_{\mathrm{mod}}^\ast,\) \(\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{exports}}~\href{../exec/runtime.html#syntax-exportinst}{\mathit{exportinst}}^\ast\}\)。
返回 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}\)。
其中
这里,符号 \(\mathrm{allocx}^\ast\) 是多个 分配 对象类型 \(X\) 的简写,定义如下:
此外,如果省略号 \(\dots\) 是一个序列 \(A^n\)(如全局变量或表格),则此序列的元素将逐点传递给分配函数。
注意
模块分配的定义与其关联函数的分配是相互递归的,因为生成的模块实例 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}\) 作为参数传递给函数分配器,以形成必要的闭包。在实现中,这种递归可以通过在辅助步骤中更改一个或另一个来轻松地解开。
实例化¶
给定一个 存储 \(S\),一个 模块 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}\) 使用 外部值 \(\href{../exec/runtime.html#syntax-externval}{\mathit{externval}}^n\) 的列表进行实例化,如下所示,这些值提供所需的导入。
实例化检查模块是否 有效 以及提供的导入是否 匹配 已声明的类型,否则可能会 *失败* 并出现错误。实例化也可能导致来自初始化活动段的表格或内存或执行开始函数的 陷阱。由 嵌入器 定义如何报告此类条件。
如果 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}\) 不是 有效 的,则
失败。
断言:\(\href{../syntax/modules.html#syntax-module}{\mathit{module}}\) 是 有效 的,具有 外部类型 \(\href{../syntax/types.html#syntax-externtype}{\mathit{externtype}}_{\mathrm{im}}^m\) 对其 导入 进行分类。
如果 导入 的数量 \(m\) 不等于提供的 外部值 的数量 \(n\),则
失败。
对于 \(\href{../exec/runtime.html#syntax-externval}{\mathit{externval}}^n\) 中的每个 外部值 \(\href{../exec/runtime.html#syntax-externval}{\mathit{externval}}_i\) 和 \(\href{../syntax/types.html#syntax-externtype}{\mathit{externtype}}_{\mathrm{im}}^n\) 中的 外部类型 \(\href{../syntax/types.html#syntax-externtype}{\mathit{externtype}}'_i\),执行以下操作:
如果 \(\href{../exec/runtime.html#syntax-externval}{\mathit{externval}}_i\) 在存储 \(S\) 中不是 有效 的,且具有 外部类型 \(\href{../syntax/types.html#syntax-externtype}{\mathit{externtype}}_i\),则
失败。
如果 \(\href{../syntax/types.html#syntax-externtype}{\mathit{externtype}}_i\) 不 匹配 \(\href{../syntax/types.html#syntax-externtype}{\mathit{externtype}}'_i\),则
失败。
令 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}_{\mathrm{init}}\) 为辅助模块 实例 \(\{\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{globaladdrs}}~\href{../exec/runtime.html#syntax-externval}{\mathrm{globals}}(\href{../exec/runtime.html#syntax-externval}{\mathit{externval}}^n), \href{../exec/runtime.html#syntax-moduleinst}{\mathsf{funcaddrs}}~\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}.\href{../exec/runtime.html#syntax-moduleinst}{\mathsf{funcaddrs}}\}\),它仅包含导入的全局变量以及来自最终模块实例 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}\)(定义如下)的导入和分配的函数。
令 \(F_{\mathrm{init}}\) 为辅助 帧 \(\{ \href{../exec/runtime.html#syntax-frame}{\mathsf{module}}~\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}_{\mathrm{init}}, \href{../exec/runtime.html#syntax-frame}{\mathsf{locals}}~\epsilon \}\)。
将帧 \(F_{\mathrm{init}}\) 推入堆栈。
令 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}^\ast\) 为由 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}\) 和 \(\href{../exec/runtime.html#syntax-externval}{\mathit{externval}}^n\) 确定的 全局 初始化 值 的向量。这些可以按如下方式计算。
对于 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}.\href{../syntax/modules.html#syntax-module}{\mathsf{globals}}\) 中的每个全局变量 \(\href{../syntax/modules.html#syntax-global}{\mathit{global}}_i\),执行以下操作
令 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}_i\) 为 评估 初始化表达式 \(\href{../syntax/modules.html#syntax-global}{\mathit{global}}_i.\href{../syntax/modules.html#syntax-global}{\mathsf{init}}\) 的结果。
断言:由于 验证,帧 \(F_{\mathrm{init}}\) 现在位于堆栈顶部。
令 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}^\ast\) 为 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}_i\) 按索引顺序的串联。
令 \((\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}^\ast)^\ast\) 为由 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}\) 中的 元素段 确定的 引用 向量列表。这些可以按如下方式计算。
对于 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}.\href{../syntax/modules.html#syntax-module}{\mathsf{elems}}\) 中的每个 元素段 \(\href{../syntax/modules.html#syntax-elem}{\mathit{elem}}_i\),以及对于 \(\href{../syntax/modules.html#syntax-elem}{\mathit{elem}}_i.\href{../syntax/modules.html#syntax-elem}{\mathsf{init}}\) 中的每个元素 表达式 \(\href{../syntax/instructions.html#syntax-expr}{\mathit{expr}}_{ij}\),执行以下操作:
令 \(\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}_{ij}\) 为对初始化表达式 \(\href{../syntax/instructions.html#syntax-expr}{\mathit{expr}}_{ij}\) 进行 求值 的结果。
令 \(\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}^\ast_i\) 为按照索引 \(j\) 的顺序连接函数元素 \(\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}_{ij}\) 的结果。
令 \((\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}^\ast)^\ast\) 为按照索引 \(i\) 的顺序连接函数元素向量 \(\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}^\ast_i\) 的结果。
从栈中弹出帧 \(F_{\mathrm{init}}\)。
令 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}\) 为一个新的模块实例,该实例从存储 \(S\) 中的 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}\) 分配,具有导入 \(\href{../exec/runtime.html#syntax-externval}{\mathit{externval}}^n\)、全局初始化值 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}^\ast\) 和元素段内容 \((\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}^\ast)^\ast\),并令 \(S'\) 为模块分配产生的扩展存储。
令 \(F\) 为辅助 帧 \(\{ \href{../exec/runtime.html#syntax-frame}{\mathsf{module}}~\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}, \href{../exec/runtime.html#syntax-frame}{\mathsf{locals}}~\epsilon \}\)。
将帧 \(F\) 推入栈中。
对于 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}.\href{../syntax/modules.html#syntax-module}{\mathsf{elems}}\) 中的每个 元素段 \(\href{../syntax/modules.html#syntax-elem}{\mathit{elem}}_i\),其 模式 为 \(\href{../syntax/modules.html#syntax-elemmode}{\mathsf{active}}~\{ \href{../syntax/modules.html#syntax-elem}{\mathsf{table}}~\href{../syntax/modules.html#syntax-tableidx}{\mathit{tableidx}}_i, \href{../syntax/modules.html#syntax-elem}{\mathsf{offset}}~\mathit{einstr}^\ast_i~\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{end}} \}\) 形式,执行以下操作:
令 \(n\) 为向量 \(\href{../syntax/modules.html#syntax-elem}{\mathit{elem}}_i.\href{../syntax/modules.html#syntax-elem}{\mathsf{init}}\) 的长度。
执行 指令序列 \(\mathit{einstr}^\ast_i\)。
执行 指令 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{i32}}.\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{const}}~0\)。
执行 指令 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{i32}}.\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{const}}~n\)。
执行 指令 \(\href{../syntax/instructions.html#syntax-instr-table}{\mathsf{table.init}}~\href{../syntax/modules.html#syntax-tableidx}{\mathit{tableidx}}_i~i\)。
执行 指令 \(\href{../syntax/instructions.html#syntax-instr-table}{\mathsf{elem.drop}}~i\)。
对于 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}.\href{../syntax/modules.html#syntax-module}{\mathsf{elems}}\) 中的每个 元素段 \(\href{../syntax/modules.html#syntax-elem}{\mathit{elem}}_i\),其 模式 为 \(\href{../syntax/modules.html#syntax-elemmode}{\mathsf{declarative}}\) 形式,执行以下操作:
执行 指令 \(\href{../syntax/instructions.html#syntax-instr-table}{\mathsf{elem.drop}}~i\)。
对于 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}.\href{../syntax/modules.html#syntax-module}{\mathsf{datas}}\) 中的每个 数据段 \(\href{../syntax/modules.html#syntax-data}{\mathit{data}}_i\),其 模式 为 \(\href{../syntax/modules.html#syntax-datamode}{\mathsf{active}}~\{ \href{../syntax/modules.html#syntax-data}{\mathsf{memory}}~\href{../syntax/modules.html#syntax-memidx}{\mathit{memidx}}_i, \href{../syntax/modules.html#syntax-data}{\mathsf{offset}}~\mathit{dinstr}^\ast_i~\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{end}} \}\) 形式,执行以下操作:
断言:\(\href{../syntax/modules.html#syntax-memidx}{\mathit{memidx}}_i\) 为 \(0\)。
令 \(n\) 为向量 \(\href{../syntax/modules.html#syntax-data}{\mathit{data}}_i.\href{../syntax/modules.html#syntax-data}{\mathsf{init}}\) 的长度。
执行 指令序列 \(\mathit{dinstr}^\ast_i\)。
执行 指令 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{i32}}.\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{const}}~0\)。
执行 指令 \(\href{../syntax/types.html#syntax-valtype}{\mathsf{i32}}.\href{../syntax/instructions.html#syntax-instr-numeric}{\mathsf{const}}~n\)。
执行 指令 \(\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{memory.init}}~i\)。
执行 指令 \(\href{../syntax/instructions.html#syntax-instr-memory}{\mathsf{data.drop}}~i\)。
如果 起始函数 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}.\href{../syntax/modules.html#syntax-module}{\mathsf{start}}\) 不为空,则
令 \(\href{../syntax/modules.html#syntax-start}{\mathit{start}}\) 为 起始函数 \(\href{../syntax/modules.html#syntax-module}{\mathit{module}}.\href{../syntax/modules.html#syntax-module}{\mathsf{start}}\)。
执行 指令 \(\href{../syntax/instructions.html#syntax-instr-control}{\mathsf{call}}~\href{../syntax/modules.html#syntax-start}{\mathit{start}}.\href{../syntax/modules.html#syntax-start}{\mathsf{func}}\)。
断言:由于 验证,帧 \(F\) 现在位于栈顶。
从栈中弹出帧 \(F\)。
其中
注意
模块 分配 和 评估 全局 初始化程序和 元素段 是相互递归的,因为全局初始化 值 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}^\ast\) 和元素段内容 \((\href{../exec/runtime.html#syntax-ref}{\mathit{ref}}^\ast)^\ast\) 被传递给模块分配器,同时依赖于模块实例 \(\href{../exec/runtime.html#syntax-moduleinst}{\mathit{moduleinst}}\) 和分配返回的存储 \(S'\)。但是,这种递归只是一个规范工具。在实践中,初始化值可以 预先确定,方法是分阶段进行模块分配,首先,在存储中预分配模块自己的 函数实例,然后评估初始化表达式,然后分配模块实例的其余部分,最后将新函数实例的 \(\href{../exec/runtime.html#syntax-frame}{\mathsf{module}}\) 字段设置为该模块实例。这是可能的,因为 验证 确保初始化表达式实际上不能调用函数,只能获取它们的引用。
在发生任何可观察到的存储修改之前,都会检查所有失败条件。存储修改不是原子的;它以可能与其他线程交错的单个步骤发生。
调用¶
一旦 模块 被 实例化,任何导出的函数都可以通过其 函数地址 \(\href{../exec/runtime.html#syntax-funcaddr}{\mathit{funcaddr}}\) 在 存储 \(S\) 中以及适当的参数 值 列表 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}^\ast\) 从外部进行 调用。
如果参数不符合 函数类型,则调用可能会 失败 并出现错误。调用也可能导致 陷阱。由 嵌入器 定义如何报告此类条件。
注意
如果 嵌入器 API 在执行调用之前,静态或动态地自行执行类型检查,则不会发生除陷阱之外的其他故障。
执行以下步骤
断言:\(S.\href{../exec/runtime.html#syntax-store}{\mathsf{funcs}}[\href{../exec/runtime.html#syntax-funcaddr}{\mathit{funcaddr}}]\) 存在。
令 \(\href{../exec/runtime.html#syntax-funcinst}{\mathit{funcinst}}\) 为 函数实例 \(S.\href{../exec/runtime.html#syntax-store}{\mathsf{funcs}}[\href{../exec/runtime.html#syntax-funcaddr}{\mathit{funcaddr}}]\)。
令 \([t_1^n] \href{../syntax/types.html#syntax-functype}{\rightarrow} [t_2^m]\) 为 函数类型 \(\href{../exec/runtime.html#syntax-funcinst}{\mathit{funcinst}}.\href{../exec/runtime.html#syntax-funcinst}{\mathsf{type}}\)。
如果提供的参数值的长度 \(|\href{../exec/runtime.html#syntax-val}{\mathit{val}}^\ast|\) 与预期参数的数量 \(n\) 不同,则
失败。
对于 \(t_1^n\) 中的每个 值类型 \(t_i\) 和 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}^\ast\) 中对应的 值 \(val_i\),执行
如果 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}_i\) 对值类型 \(t_i\) 不是 有效的,则
失败。
令 \(F\) 为虚拟 帧 \(\{ \href{../exec/runtime.html#syntax-frame}{\mathsf{module}}~\{\}, \href{../exec/runtime.html#syntax-frame}{\mathsf{locals}}~\epsilon \}\)。
将帧 \(F\) 推入栈中。
将值 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}^\ast\) 推送到堆栈。
调用 地址为 \(\href{../exec/runtime.html#syntax-funcaddr}{\mathit{funcaddr}}\) 的函数实例。
函数返回后,执行以下步骤
从堆栈中弹出 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}_{\mathrm{res}}^m\)。
断言:由于 验证,帧 \(F\) 现在位于栈顶。
从栈中弹出帧 \(F\)。
值 \(\href{../exec/runtime.html#syntax-val}{\mathit{val}}_{\mathrm{res}}^m\) 作为调用的结果返回。