V8引擎如何执行JavaScript代码的?

8/5/2022 编译器解析器AST机器码

# 前言

关于V8:

  • Google Chrome浏览器、Node.js的一部分。
  • 负责去解析执行JavaScript代码。

JavaScript自身是轻量级解释型语言。从技术层面看,现代浏览器引擎都采用了即时编译(Just-In-Time Compiling)技术让源码执行的更快。
机器无法直接理解我们所写的代码,所以执行代码之前,需要先把代码”翻译(编译器、解释器)“成机器能理解的机器语言。一般可以把语言分为两类:编译型、解释型。上面说的即时编译,意思是编译 + 解释的结合体。MDN - JavaScript (opens new window)

一切都是为了执行效率

# 为何采用先编译后解释执行的方案呢?

JavaScript每次执行都要去先编译再去执行,为什么不能像Java一样,一次编译成可执行文件,“随处”运行呢?这样不就不用每次执行都要走一遍编译流程了嘛?
问题点:

  • 无法统一客户用的浏览器版本(Java执行文件我们是可以指定运行环境和版本的)。
  • ECMAScript本身规范也不断的更新(JavaScript这种语言面对文本展示的场景,更新频率比Java快)。
  • 各家浏览器厂商对于JavaScript语言特性支持度不统一。

面对这些情况下,如果让JavaScript编译成“可执行”文件,很有可能出现某些浏览器运行不了,某些语言特性失效。所以让JavaScript编译成可执行文件这种提案目前来说比较难推进。 二进制AST提案 (opens new window)

# 编译器、解释器

# 编译型语言执行流程

编译过程:源代码 => 词法分析、语法分析 => 生成抽象语法树(AST) => 优化代码 => 生成机器码
若编译成功,生成一个可执行文件,若编译发生错误,编译器会抛出异常,停止编译。

# 解释型语言执行流程

解释过程:源代码 => 词法分析、语法分析 => 生成抽象语法树(AST) => 生成字节码 => 执行程序。

# 字节码和机器码

字节码介于AST和机器码中间。需要通过解释器转成机器码才能执行。 字节码所占用的内存比机器码要小

# V8执行流程

V8执行过程中,同时有用到编译器(TurboFan)和解释器(Ignition)

TurboFan:涡轮增压发动机 => 负责加速、优化代码执行效率
Ignition:点火器 => 负责启动、负责执行代码

# 总览

源代码 => 词法分析、语法分析 => 生成抽象语法树(AST)、执行上下文 => 生成字节码 => 执行代码(执行的过程中不断优化)

# 生成抽象语法树(AST)、执行上下文

我们能够理解的是高级语言,对于编译器、解释器能理解的是AST。有点类似于浏览器的渲染引擎能理解HTML文件生成的DOM树。
AST是一种比较重要的数据结构,我们平时碰到的Babel(JS转码)、ESLint(检查JavaScript编写规范)都有涉及。

Babel:ES6转ES5 => ES6源码转成AST => 转成ES5的AST => 生成JavaScript源码。
ESLint:源码转AST => 分析AST检查代码规范。

生成AST的两个阶段:

  1. 词法分析(tokenize)
    将源码一行行拆解为一个个的token(在语法上不可再分、最小的单个字符或字符串)。
  2. 解析(parse)
    将生成的token,依据语法规则生成AST。代码若有语法错误,在这一步会中止,抛出语法错误 。

生成AST后,继续生成执行上下文

# 生成字节码

此时需要解释器(Ignition)根据AST去生成字节码,并且执行。

在过去,V8并没有字节码的引入,直接是AST转成机器码,机器码的执行效率是很高的。但是随着时代的变迁,移动端的发展,浏览器在手机上运行,手机本身内存会小,V8需要消耗很多内存去保存转换的机器码,为了解决这个内存占用的问题,V8重构引入字节码。

# 执行代码

解释器(Ignition)逐条执行字节码,执行过程中若发现热点代码(HotSpot、经常需要重复执行的代码),通过编译器(TurboFan)将热点代码的字节码编译为高效的机器码,当代码再次执行,直接执行机器码,提高效率。所以说JavaScript代码越执行越久越快哈哈哈
这种字节码配合解释器和编译器的技术,称之为即时编译(JIT)

# 我们自身如何去优化JavaScript执行效率

  • 提升单次脚本执行速度,避免JavaScript霸占主线程很久,让页面能快速响应交互。
  • 避免内联脚本,解析JavaScript的过程中,解析、编译也是会占用主线程的。
  • 减少JavaScript文件大小,文件越小,提高下载速度,减少内存占用。
Last Updated: 11/2/2022, 5:11:53 PM