V8 执行过程
一、编译器和解释器的基本概念
在计算机科学中,源代码需要被转换成机器码才能被执行。这个转换过程根据不同的编程语言有两种主要方式:
- 编译型语言:
C/C++、GO
在编译型语⾔的编译过程中,编译器⾸先会依次对源代码进⾏词法分析、语法分析,⽣成抽象语法树(AST),然后是优化代码,最后再⽣成处理器能够理解的机器码。如果编译成功,将会⽣成⼀个可执⾏的⽂件。但如果编译过程发⽣了语法或者其他的错误,那么编译器就会抛出异常,最后的⼆进制⽂件也不会⽣成成功。 - 解释型语言:
JavaScript、Python
在解释型语⾔的解释过程中,同样解释器也会对源代码进⾏词法分析、语法分析,并⽣成抽象语法树(AST),不过它会再基于抽象语法树⽣成字节码,最后再根据字节码来执⾏程序、输出结果。
二、V8 执行 JavaScript 的详细流程
V8引擎执行JavaScript代码主要分为以下几个关键步骤:
2.1 生成抽象语法树(AST)
2.1.1 词法分析(Tokenize)
将源码分解成最小的语法单元(Token)。例如:
javascript
var name = "V8";
1
会被分解为以下Token:
- 关键字:
var
- 标识符:
name
- 操作符:
=
- 字符串:
"V8"
2.1.2 语法分析(Parse)
将 Token
转换为 AST
(抽象语法树)。AST
是源码的树状结构表示,每个节点代表代码中的一个语法结构。
AST 在前端开发中的应用
- Babel:实现JavaScript版本转换 (先将 ES6 源码转换为 AST,然后再将 ES6 语法的 AST 转换为 ES5 语法的 AST,最后利⽤ ES5 的 AST ⽣成 JavaScrip)
- ESLint:进行代码规范检查
- 代码压缩工具:如terser
- 代码高亮:编辑器的语法高亮功能
2.2 生成字节码
V8的解释器 Ignition
会将 AST
转换为字节码。字节码相比机器码有以下优势:
- 占用空间更小
- 可以跨平台执行
- 执行效率介于
AST
和机器码之间
2.3 执行优化
V8采用了 JIT(即时编译)技术来优化代码执行:
通常,如果有⼀段第⼀次执⾏的字节码,解释器 Ignition 会逐条解释执⾏。在执⾏字节码的过程中,如果发现有热点代码(HotSpot),⽐如⼀段代码被重复执⾏多次,这种就称为热点代码,那么后台的编译器 TurboFan 就会把该段热点的字节码编译为⾼效的机器码,然后当再次执⾏这段被优化的代码时,只需要执⾏编译后的机器码就可以了,这样就⼤⼤提升了代码的执⾏效率。 此之谓即时编译(JIT)
性能优化
V8的这种混合执行模式既保证了启动速度,又能在运行时达到接近编译语言的性能。