首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

WebAssembly与RISC-V 指令集架构的对比

WebAssembly 与 RISC-V 都是近十年内新出现的指令集架构。摘录一段 WebAssembly 官方网站的介绍:

WebAssembly (abbreviatedWasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable target for compilation of high-level languages like C/C++/Rust, enabling deployment on the web for client and server applications.

WebAssembly (简写为 Wasm)是一种栈虚拟机的二进制指令格式。Wasm 被设计为 C/C++/Rust 等高级语言的可移植编译目标,从而允许客户端和服务器应用程序部署在 Web 上。

和 RISC-V 的官方介绍:

RISC-V is a free and open ISA enabling a new era of processor innovation through open standard collaboration. Born in academia and research, RISC-V ISA delivers a new level of free, extensible software and hardware freedom on architecture, paving the way for the next 50 years of computing design and innovation.

RISC-V 是一种自由、开放的指令集架构,通过开放标准协作使新的处理器创新成为可能。RISC-V 来自学术研究,提供了更加自由、可扩展的软硬件架构,为未来 50 年的计算技术设计与创新铺平道路。

这两种指令集架构看起来很不一样。WebAssembly 的目标平台主要是 JIT 编译器(以及浏览器);而 RISC-V 则专为硬件设计,其目标之一即是在 FPGA 和电路上的高效实现。WebAssembly 与 RISC-V 的关系似乎类似于早期的 Java 与 x86:一种字节码格式,和一个硬件指令集。它们有什么关系呢?

其实字节码格式与硬件指令集的分界线并不是非常清晰。例如在 x86 指令集的早期实现中,指令经过一层解码直接被分发到执行电路去执行。但近年的 Intel/AMD CPU 采用了不同的执行策略:每条 x86 指令首先被翻译为某种内部 RISC 指令,执行组件收到的指令其实已经是翻译后的 RISC 编码格式。这实际上相当于从 x86 到内部 RISC 指令集的某种“硬件实时编译”过程。同时,Java 与 WebAssembly 也有实验性的硬件实现,虽然它们还不能赶上 JIT 编译器在现代 CPU 上所能达到的效率。

我们已经可以看到 RISC-V 指令集被用于区块链的智能合约,而 WebAssembly 此前几乎是原生语言智能合约的唯一选择。

在这里我们对 WebAssembly 与 RISC-V 做一个比较。

1. 代码/数据分离

包括 RISC-V 在内的大多数现代架构对代码和数据使用同一个地址空间,但是 WebAssembly 没有这样做。实际上,运行中的代码甚至没有办法读/写它自己。这个设计的原因可能是:

简化 JIT 编译器的实现。如果代码可以自我修改,那么 JIT 编译器则需要有检测修改和重新生成目标代码的能力,而这需要相当复杂的实现机制。

WebAssembly 假设了一个功能完善的运行环境。运行环境会处理链接、重定位等准备工作,程序不需要关心怎样把它自己运行起来。

安全。能够动态生成和修改的代码是个很危险的攻击点。

2. 静态类型与控制流约束

WebAssembly 具有很强的“结构性”。其标准要求所有函数调用、循环、跳转和值类型遵循特定的结构约束,例如向一个接受三个参数的函数传入两个参数、跳转到其他函数里的某个位置、在两个整数上执行浮点加操作等都会导致编译/验证失败。RISC-V 则不具有此类约束,指令的有效与否只取决于其自身的编码是否正确。

3. 机器模型

WebAssembly 是一种栈机指令集,而 RISC-V 是一种寄存器机指令集。

在 WebAssembly 中,每条指令语义上会从值栈上弹出它的操作数,然后将结果推入值栈。然而与 Java 等其他基于栈机的字节码格式不同的是,程序中任意指令处值栈的结构都可以被静态确定。这一设计有利于更好的编译优化。

在 RISC-V 中,每条指令的编码包含 0 - 3 个寄存器编号。其中与是输入寄存器,是输出寄存器。除内存访问、特权指令等特殊类型指令外,每条指令只从输入寄存器中读取数据,在输出寄存器中存放结果。

4. 内存管理

虽然 WebAssembly 与 RISC-V 都定义了一个无类型的、字节可寻址的内存,它们之间还是有一些细节上的区别。WebAssembly 的内存等同于一个大数组:有效地址从 0 开始,连续扩展到某个由程序定义初值、可增长的上限。而 RISC-V 则使用了虚拟内存,用页表将地址映射到物理内存。

内存布局

WebAssembly 的内存设计虽然简洁且易于实现,但存在一些问题:

地址 0 是有效的,这会导致一些程序在解引用空指针时的行为与预期不同。

无法建立不映射到任何物理地址的“无效”地址区间,因此无法实现多线程环境下的栈保护页 (guard page) 。

5. 同步机制

图灵完备的计算机器需要至少一条条件分支指令。同样,支持多线程同步的指令集架构需要至少一条“原子条件分支”指令。这类指令在 WebAssembly 下是,在 RISC-V 下是,分别对应 CAS 模型和 LL/SC 模型。

LL/SC 的语义比 CAS 更强。CAS 存在难以解决的 ABA 问题,但 LL/SC 不受影响。这也意味着在 CAS 架构上模拟 LL/SC 比反过来要困难很多。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200316A0FW4B00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券