前言
今天看了一个视频,关于V8
引擎是如何运行JS
的。我将视频中主要的知识点记下来,一来加深记忆,二来方便复习
什么是V8
V8
是使用C++
编写的Google
开源高性能JavaScript
和WebAssembly
引擎。V8
第一个版本随着第一个版本的Chrome
于2008
年9
月2
日发布
哪些程序用到V8
-
Chrome
浏览器的JS
引擎是V8
-
Nodejs
的运行时环境是V8
-
electron
的底层引擎是V8
V8主要职责
简单来说,V8
是一个接收JavaScript
代码,编译代码然后执行C++
程序,编译后的代码可以在多种操作系统多种处理器上运行。其主要职责:
- 编译和执行
JS
代码 - 处理调用栈
- 内存分配
- 垃圾回收
V8如何编译和执行JS代码
一般来说,JS
引擎在编译和执行代码都会用到三个重要的组件,分别:
- 解析器 --> 负责将
JS
源代码解析成抽象语法树AST
- 解释器 --> 负责将
AST
解析成字节码bytecode
,同时解释器也有解释执行bytecode
的能力
- 编译器 --> 负责编译出运行更加高效的机器代码
但是在V8
早期,在5.9
版本以前,是没有解释器,但有两个编译器,其编译流程如下
-
parser
解释器生成抽象语法树AST
-
compiler
编译器Full-codegen
基准编译器 直接生成机器码 - 运行一段时间后,由分析器线程优化
js
代码 -
compiler
编译器CrankShaft
优化编译器 重新生成AST
提升运行效率
这样设计的缺点
- 机器码会占用大量的内存
- 缺少中间层机器码,无法实现一些优化策略
- 无法很好的支持和优化
JS
的新语特性,无法拥抱未来
正因为存在以上问题,V8
团队用了三年半的时间,开发了一套新的V8
架构
新版本的V8
-
parser
解析器 生成AST
抽象语法树 -
interpreter
解释器Ignition
生成byteCode
字节码 并直接执行 - 清除
AST
释放内存空间 - 得到
25% - 50%
的等效机器代码大小 -
compiler
运行过程中,解释器收集优化信息发送给编译器TurboFan
- 重新生成机器码
- 有些热点函数变更会由优化后的机器码还原成字节码 也就是
deoptimization
回退字节码操作执行
优化点:
- 值声明未调用,不会被解析生成
AST
- 函数只被调用一次,
bytcode
直接被解释执行,不会进入到编译优化阶段 - 函数被调用多次,
Igniton
会收集函数类型信息,可能会被标记为热点函数,可能被编译成优化后的机器代码
好处:
- 由于一开始不需要直接编译成机器码,生成了中间层的字节码,从而节约了时间
- 优化编译阶段,不需要从源码重新解析,直接通过字节码进行优化,也可以
deoptimization
回退操作
如:
function sum(x,y){return x + y};
sum(1,2);
sum(3,4);
sum(5,6);
sum("7","8");//会回退字节码操作执行
以上就是V8引擎如何运行JS相关内容
原视频:https://www.bilibili.com/video/BV1zV411z7RX
作者:luke
个人推荐多看两遍