13 V8如何解析js代码 - 编译器+解析器

Posted by CodingWithAlice on April 11, 2021

13 V8如何解析js代码 - 编译器+解释器

1、语言类型分类

解释型语言 – js、python等,每次都需要 解释器 对程序进行动态解释和执行 编译型语言 – C/C++、GO等,需要编译,编译后生成 二进制文件 并保留,下次可以直接执行

image-20210411201357930

2、概览V8解析一段js代码

流程概括:V8 依据 JavaScript 代码生成 AST 和执行上下文,再基于 AST 生成 字节码,然后通过 解释器执行字节码,通过 编译器来优化编译字节码

image-20210411201445395

3、详细步骤拆解

1/4、生成抽象语法树(AST)

第一阶段是分词(tokenize),又称为词法分析,将一行行的源码 拆解 成一个个 token。 第二阶段是解析(parse),又称为语法分析,是将上一步生成的 token 数据,根据语法规则转为 AST

拓展:AST被应用于多个项目中,包括Babel、ESlint。

  • Babel 的工作原理就是先将 ES6 源码转换为 AST,然后再将 ES6 语法的 AST 转换为 ES5 语法的 AST,最后利用 ES5 的 AST 生成 JavaScript 源代码。
  • ESLint 检测流程也是需要将源码转换为 AST,然后再利用 AST 来检查代码规范化的问题

2/4、 V8 会生成该段代码的执行上下文

3/4、生成字节码 - 解释器 Ignition

补充:字节码就是介于 AST 和机器码之间的一种代码。

使用字节码可以减少系统的内存使用,如下图。

与特定类型的机器码无关,字节码需要通过 解释器 将其转换为机器码后才能执行。

image-20210411201742032

4/4、执行代码 - 即时编译(JIT)

​ 第一次执行的字节码,解释器 Ignition 会逐条解释执行;如果一段代码里面有热点代码(HotSpot一段代码被重复执行多次)那么后台的 编译器 TurboFan 就会把该段热点的字节码编译为高效的机器码,然后当再次执行这段被优化的代码时,只需要执行编译后的机器码就可以了,这样就大大提升了代码的执行效率。

​ 即时编译(JIT) - 在很多技术中都实现了,在V8中就是指解释器 Ignition 在解释执行字节码的同时,收集代码信息,当它发现某一部分代码变热了之后,TurboFan 编译器便闪亮登场,把热点的字节码转换为机器码,并把转换后的机器码保存起来,以备下次使用。

image-20210411201832983