13 V8如何解析js代码 - 编译器+解释器
1、语言类型分类
解释型语言 – js、python等,每次都需要 解释器 对程序进行动态解释和执行 编译型语言 – C/C++、GO等,需要编译,编译后生成 二进制文件 并保留,下次可以直接执行
2、概览V8解析一段js代码
流程概括:V8 依据 JavaScript 代码生成 AST 和执行上下文,再基于 AST 生成 字节码,然后通过 解释器执行字节码,通过 编译器来优化编译字节码
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 和机器码之间的一种代码。
使用字节码可以减少系统的内存使用,如下图。
与特定类型的机器码无关,字节码需要通过 解释器 将其转换为机器码后才能执行。
4/4、执行代码 - 即时编译(JIT)
第一次执行的字节码,解释器 Ignition 会逐条解释执行;如果一段代码里面有热点代码(HotSpot一段代码被重复执行多次)那么后台的 编译器 TurboFan 就会把该段热点的字节码编译为高效的机器码,然后当再次执行这段被优化的代码时,只需要执行编译后的机器码就可以了,这样就大大提升了代码的执行效率。
即时编译(JIT) - 在很多技术中都实现了,在V8中就是指解释器 Ignition 在解释执行字节码的同时,收集代码信息,当它发现某一部分代码变热了之后,TurboFan 编译器便闪亮登场,把热点的字节码转换为机器码,并把转换后的机器码保存起来,以备下次使用。