WebAssembly进阶系列二:WebAssembly处于编译阶段哪一个环节

导语:相信很多人据说过 WebAssembly,它是由 Google、Microsoft、Mozilla、Apple 等几家大公司合做发起的一个关于面向Web的通用二进制和文本格式的项目。如今就让咱们一步步揭开WebAssembly的神秘面纱,并亲自动手将WebAssembly应用在实际业务中。前端

1. 引言

众所周知,不管是Chrome、Firefox、Safari、Edge仍是其余浏览器,可以运行的语言就是Javascript。为了可以让其余语言的代码在浏览器中运行,WebAssembly被创造出来,详见《WebAssembly进阶系列二:WebAssembly是什么》。咱们并不须要亲自编写WebAssembly的代码,惟一要作的就是把其余高级语言编译成WebAssembly便可,这样便能复用大量其余语言现有的代码。并且WebAssembly还拥有比JavaScript更好的性能,可以更快的加载和执行。git

那为啥WebAssembly的性能就必定会比JavaScript好不少呢?具体缘由还得看下它们究竟是处于编译阶段哪一个环节了。程序员

2. 编译步骤

做为程序员的咱们,天天都在用各类高级语言写源代码。但要让机器能读懂这些字符串代码,就得靠编译系统一步步把它们编译成目标代码。github

(1) 预编译web

预编译首先会处理源代码中那些以#开头(如#include、#define等)的预编译指令,在编译开始前就先对原始的代码文件进行调整。通过了预编译以后,你写的代码其实已经有了很大的变化。编程

(2) 词法分析后端

词法分析是计算机科学中将字符序列转换为单词(Token)序列的过程。进行词法分析的程序或者函数叫做词法分析器(lexical analyzer,简称lexer),也叫扫描器(Scanner),供语法分析器调用。浏览器

词法分析阶段是编译过程的第一个阶段,任务是从左到右以字符流的方式逐行扫描源代码,而后根据构词规则一一识别关键词、标志符、字面量、运算符等,并分割成一个个按顺序排列的标记Token。编程语言

(3) 语法分析模块化

语法分析是根据某种给定的形式文法对由单词序列(如英语单词序列)构成的输入文本进行分析并肯定其语法结构的一种过程。进行语法分析的程序或者函数叫做语法分析器(parser),供语义分析调用。

语法分析阶段是编译过程的一个逻辑阶段,任务是在词法分析分割出来的标记Token的基础上,将Token序列组合成各种语法短语如“程序”、“语句”、“表达式”等。

(4) 语义分析

语义分析是编译过程的一个最实质性的阶段,任务是对结构上正确的源代码进行上下文有关性质的审查,进行类型审查。

其实通过语法分析以后就能初步获得了抽象语法树,树上的每一个节点都是一个表达式,但此时还不肯定是否有意义。因而须要经过语义分析,遍历整个抽象语法树,把每一个节点的表达式都标识类型,而且验证是否合法。

(5) 抽象语法树

抽象语法树(Abstract Syntax Tree,AST),是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每一个节点都表示源代码中的一种结构,以下图所示:

从语法分析开始,就已经生成了初步的抽象语法树。通过了语义分析以后,抽象语法树又变得更加完善,自此最终版的抽象语法树AST已经创建完成。

(6) 中间码

通过前面几个阶段以后,咱们已经有了最终版的AST。可是该AST并不能完美运行在各个硬件平台上,由于不一样平台的汇编处理都是不同的。

因而便在AST和多个平台的汇编代码中间,抽象出了一个中间码(Intermediate Representation),在中间码的设计里抹平了硬件平台形成的差别。中间码的强大之处在于跨平台,与语言无关。

(7) 目标代码

计算机是经过汇编指令来执行操做的,如移动到内存某个地址、位移多少个字节等。所以须要经过目标平台的汇编器,由AST转成的中间码生成目标平台的汇编代码,这些才是机器能读懂的目标代码。

3. 编译前端与后端

前面介绍了这么多编译步骤,其实咱们能够把中间码当成一个分界线,中间码之前的环节叫作编译前端,中间码之后的环节叫作编译后端。

(1) 编译前端

编译前端包括预编译、词法分析、语法分析、语义分析、抽象语法树等,专门用来处理语言专属特性。虽然不一样语言的词法关键字、语法规则、语义分析的函数类型校验可能都不同,甚至某些语言都没有预编译这个环节,但每一个语言均可以开发一套编译前端,按照标准生成的统一中间码就能够无缝对接给任意编译后端,这就是语言无关。

(2) 编译后端

编译后端这里只包含了目标代码生成部分,其实还应该包括将目标代码连接成为可执行文件的环节。编译后端专门负责处理各个平台的差别,根据不一样语言生成的标准中间码,生成对应的目标代码,这就是平台无关。

4. 编译工具

(1) GCC

GCC(GNU Compiler Collection,GNU编译器套装),包含了编译前端与编译后端全部模块。其中,编译前端部分支持C、C++、Fortran、Pascal、Objective-C、Java等语言,编译后端支持x8六、mips、Alpha、ARM、AVR、IA-6四、SPARC、PowerPC等30多种平台。

GCC虽然被普遍的使用,但目前也面临了危机。后起之秀的Clang / LLVM,大有全面赶超GCC的势头。

(2) Clang / LLVM

Clang是一个C++编写、基于LLVM、发布于LLVM BSD许可证下的C / C++ / Objective-C / Objective-C++ 的编译器。那为啥已经有了GCC后还要开发Clang呢?Clang相比于GCC有什么优点呢?由于Clang是一个高度模块化开发的轻量级编译器,它的编译速度快、占用内存小、很是方便进行二次开发。

而有了Clang这个编译器前端还不够,因而就跟LLVM这个编译器后端组合成一个完整的编译器套件,以下图所示:

5. WebAssembly在编译环节的位置

前面说了这么多,但仍是不知道WebAssembly处于编译阶段哪一个环节啊?心急吃不了热豆腐,凡事都要对基础知识有必定了解以后,才能茅塞顿开。

经过下图你即可以一目了然WebAssembly所处的位置,它能作到像Java字节码同样,一次编译处处运行,具备跨平台特性。以此同时,做为中间码的WebAssembly直接省略编译前端的步骤,而JavaScript须要实时编译,相比之下性能优点显著。

6. 写在最后

若是WebAssembly不出现,那么HTML、CSS、JavaScript将成为前端领域的事实汇编语言,浏览器最终会把它们做为“编译目标”。WebAssembly的出现则提供了一个更好的选择:接近原生的运算速度,不只拥有开源、兼容性好、跨平台覆盖广等特性,还能够借此机会抛弃JavaScript的历史遗留问题,何乐而不为呢?

参考资料

  1. WebAssembly:解决 JavaScript 痼疾的银弹?
  2. WebAssembly的过去、如今和将来
  3. 扯淡:大白话聊聊编译那点事儿
  4. LLVM相比于JVM,有哪些技术优点?
  5. WebAssembly 系列(三)编译器如何生成汇编
  6. WebAssembly入门:将字节码带入Web世界
  7. JavaScript是如何工做的:与WebAssembly比较及其使用场景
  8. LLVM编译原理和使用

我的公众号:前端开发升值记

相关文章
相关标签/搜索