- 作者:老汪软件技巧
- 发表时间:2024-08-22 15:01
- 浏览量:
JS 是一种解释型语言,不同于编译型语言,编译型语言在执行前会将源代码编译成机器码。而解释型语言则是在运行时通过解释器逐行解释并执行。
V8 是当前主流的 JS 引擎,被广泛应用于 Chrome 浏览器和 Node.js 中。V8 包含了 JS 解释器和优化编译器等组件,负责将 JS 代码解释或编译执行。
此图仅展示 V8 引擎对 JS 的处理流程,不包括 JS 代码具体的执行过程。
希望你通过这张图建立对 V8 的初步认识。各流程节点产物我写了示例,点击可以跳转查看。
JS 源码以 UTF-16 编码字符串的形式传给 V8 引擎。
词法分析阶段
V8 引擎扫描器扫描全量代码,进行词法分析,将源码分解成一系列标记(token)。
。
预解析和延迟解析
如果一个函数接下来不会被立即执行,那么这个函数仅会被预解析,将来被执行时才真正解析,这个过程就是「延迟解析」。
预解析:那些不会被马上执行的代码(比如事件驱动函数)将会被预解析,预解析会进行简单的语法检查和信息记录。相比于真正的解析,预解析仅生成一个简化的 AST(意味着不会为函数体内的代码生成详细的 AST,有助于加快初次解析)。
语法分析阶段
针对将被执行的代码,解析器会根据词法分析阶段生成的 Token 进行语法分析,生成完整的 AST 抽象语法树。此阶段代码结构确定,作用域也确定。
。
解释执行
语法分析阶段生成的 AST 抽象语法树被 JS 解释器编译成字节码并解释执行。
。
JIT 即时编译
如果一个函数被解释器执行多次则会被标记为热点代码,热点代码将会被 JS 编译器进一步优化编译成机器码并执行。这就是「JIT 即时编译技术」。
如果这段被优化编译的代码结构发生了变化(比如不符合 V8 的类型假设),那么编译器将会对这段代码「去优化」恢复成字节码,并交回解释器执行。
类型假设:热点代码在执行过程中 V8 会假设函数的入参类型一致,如果函数的入参类型改变,就会被「去优化」。
最后总结 V8 对 JS 代码的处理流程:
在 V8 引擎中,JS 代码经过扫描器词法分析生成 Token。经过解析器语法分析生成完整的 AST 抽象语法树,语法分析阶段代码结构确定,因此作用域也随之确定。接下来 AST 会被 V8 解释器解释成字节码并执行。如果一个函数被解释器执行多次则会被标记为 Hot 热点代码,热点代码会被 V8 优化编译器进一步编译成机器码并执行,如果被优化函数后续结构改变,那么被优化代码会被「去优化」恢复为字节码,重新交回解释器执行。