什么是 V8

V8 是一个由 Google 开发的开源 JavaScript 引擎(也称 JavaScript 虚拟机),目前用在 Chrome 浏览器和 Node.js 中,其核心功能是执行 JavaScript 代码

目前市面上有很多种 JavaScript 引擎,诸如 SpiderMonkey、V8、JavaScriptCore 等。而 V8 是当下使用最广泛的 JavaScript 引擎,我们写的 JavaScript 应用,大都跑在 V8 上

V8 之所以如此受欢迎,和它许多革命性的设计是分不开的:

  • V8 率先引入了即时编译(JIT)的双轮驱动的设计,这是一种权衡策略,混合编译执行和解释执行这两种手段,给 JavaScript 的执行速度带来了极大的提升
  • V8 引入了惰性编译、内联缓存、隐藏类等机制,进一步优化了 JavaScript 代码的编译执行效率

可以说,V8 的出现,将 JavaScript 虚拟机技术推向了一个全新的高度

V8 如何执行 JavaScript 代码

V8 是一个虚拟机,具有自己的一套指令系统,它屏蔽了不同体系结构计算机(如:不同的 CPU 指令集)、不同操作系统的差异

V8 并没有采用某种单一的解释执行或编译执行,而是混合这两种手段,我们把这种混合使用编译器和解释器的技术称为 JIT(Just In Time)技术

这是一种权衡策略,因为这两种方法都各自有自的优缺点:解释执行的启动速度快,但是执行时的速度慢;而编译执行的启动速度慢,但是执行时的速度快

  1. V8 启动时需要初始化一些基础环境,包括:
    • 栈空间
    • 堆空间
    • 全局执行上下文:包含了执行过程中的全局信息,如一些内置函数,全局变量等
    • 全局作用域:包含了一些全局变量
    • 消息循环系统:包含消息驱动器和消息队列
  2. V8 接收到要执行的 JavaScript 源代码字符串
  3. 通过解析器解析成抽象语法树(AST),同时生成相关的作用域,用于存放相关变量
  4. 之后就可以生成字节码了,字节码是介于 AST 和机器代码的中间代码。与特定类型的机器代码无关
  5. 解释器可以直接解释执行字节码,并输出执行结果
  6. 解释执行字节码的过程中,有一个监控模块。如果发现了某一段代码会被重复多次执行,那么就会将这段代码标记为热点代码
  7. 热点代码(字节码)会被编译器编译为二进制机器代码,由 CPU 直接执行。如果下次再执行到这段代码时,会优先选择优化之后的二进制代码,大幅提升执行速度
  8. 由于 JavaScript 是一种非常灵活的动态语言,对象的结构和属性是可以在运行时任意修改的,而经过编译器优化过的代码只能针对某种固定的结构,一旦在执行过程中,对象的结构被动态修改了,就需要执行反优化操作,回退到解释器解释执行