1、基本
接收Javascript代码,编译代码然后执行的C++程序。编译后的代码可以在多种操作系统、多种处理器运行。
2、基本引擎
2.1解析器parser
将Java Script代码解析成抽象语法树AST
2.2解释器interpreter
将AST解释成字节码bytecode
【拥有直接解释执行bytecode能力】
2.3编译器compiler
编译出运行更加高效的机器代码
3、主要负责
3.1编译和执行JS代码
3.1.1早期5.9版本之前
没有解释器有两个编译器
编译流程
1、JS由解析器解析后生成AST抽象语法树
2、然后由Full-codegen编译器直接使用AST编译出机器代码,不进行任何中间转换
(Full-codegen编译器也被称为基准编译器,因为生成的是一个基准的未被优化的机器代码)
3、运行一段时间后,由分析器线程优化js代码
4、CrankShaft优化编译器重新生成AST提升运行效率
优缺点
优点
第一次执行JS时,就是直接使用了高效的机器代码,因为没有中间的字节码产生,所以就不需要解释器
缺点
1. 机器码会占用大量的内存
2. 缺少中间层机器码,无法实现一些优化策略
3. 无法很好的支持和优化JS的新语特性,无法拥抱未来
3.1.2现在
编译流程
1、JS由解析器解析后生成AST抽象语法树
2、解释器 Ignition 生成byteCode字节码 并直接执行
(清除AST 释放内存空间)
3. 解释器执行bytecode
(此时的bytecode将被作为基准执行模型)
4. 得到25% - 50%的等效机器代码大小
(是以第三部生成的bytecode作为基准执行模型,字节码更简洁)
5. compiler 运行过程中,解释器收集优化信息发送给编译器TurboFan
6. 重新生成机器码
7. 有些热点函数变更会由优化后的机器码还原成字节码
也就是deoptimization 回退字节码操作执行
JavaScript是动态语言,对于函数参数或者是变量声明的不严谨,可能会导致Ignition收集到的信息经由TurboFan处理后生成的机器代码的参数类型
与实际传入参数类型
有所出入。
比如:sum(a,b)=>{return a+b}
函数,Ignition之前一直收集到的信息a,b都是int类型,但是有次调用传了字符串,就会导致机器代码无法解释,那么此时的V8就会回退字节码操作执行
优化策略
1、函数值只声明未被调用,不会被解析生成ast
2、函数只被调用一次,bytecode直接解释执行
3、函数被调用多次,可能会被标记为热点函数,可能会被编译成机器代码
对于优化策略2的一些解释
就是说他会直接调用第三步的bytecode不会到TurboFan,
因为TurboFan需要收集之前执行时的类型信息,
那么就意味着TurboFan的优化对象函数至少执行大于一次
对于优化策略3的一些解释
就是说当函数被标记为热点函数后,Ignition就收集了很多类型信息
那么TurboFan就会优化这些信息将bytecode生成机器代码。
后面再调用就会直接调用TurboFan生成的机器代码
优化点
由于一开始不需要直接编译成机器码,生成了中间层的字节码,从而节约了时间
优化编译阶段,不需要从源码重新解析,直接通过字节码进行优化,也可以deoptimization回退操作