V8引擎简介——如何编译和执行JS代码

1.用处

  • chrome浏览器的引擎
  • Nodejs的运行时环境
  • electron的底层引擎

2.什么是V8引擎

  •  是用C++编写的Google开源高性能JS和WebAssembly引擎
  • 简而言之:是一个接收JS代码,编译代码然后执行的C++程序,编译后的代码可以在多种操作系统,多种处理器上运行

主要的工作:

  1. 编译和执行JS代码
  2. 处理调用栈
  3. 内存的分配
  4. 垃圾的回收

3.溯源

大部分JS引擎在编译和执行JS代码都会用到三个重要的组件:

  • 解析器
    • 负责将JS源代码解析成抽象语法树AST
  • 解释器
    • 负责将AST解释成字节码bytecode
    • 也有直接解释执行bytecode的能力
  • 编译器
    • 负责编译出运行更加高效的机器代码

早期的V8引擎是如何编译和执行JS代码的:

  在V8早期5.9版本之前,V8引擎没有解释器,却有两个编译器:

  • JS由解析器解析后,生成AST抽象语法树
  • 然后由编译器(Full-codegen)直接使用AST来编译出机器代码,而不进行任何中间转换
    • Full-codegen又称基准编译器,因为它生成的是一个基准的未被优化的机器代码
  • 还有另一个编译器(Crankshaft)——优化编译器:用来优化代码,提升性能

缺陷:

  • 生成的机器码会占用大量的内存
  • 缺少中间的字节码,很多性能优化策略无法实施——V8性能提升缓慢
  • 无法很好的支持和优化JS的新语法特性

4.目前的V8引擎

  • 网页初始化解析执行JS的时间缩短了,网页能够更快的onload
  • 在生成的优化机器代码时,不需要从源码重新编译,而使用字节码,并且当需要回退字节码时,只需要回归到中间层的字节码解释执行就可以了

5.V8引擎中处理JS过程中的一些优化策略

  1. 如果函数只是声明而未被调用,则不会被解析生成AST
  2. 函数如果只被调用一次,bytecode直接被解释执行
  3. 函数被调用多次,可能会被标记为热点函数,可能会被编译成机器代码——提高代码的执行性能。
    1. 之后执行这个函数时,就直接运行优化后的机器代码 
    2. 随着JS代码的不断执行,会有更多的代码被标记为热点代码,也就会产生更多的机器代码
    3. 此时会有一个问题:回退字节码。
      1. 造成的原因是:如一个sum函数,参数是a,b,多次调用传入整数,且被识别为热点函数,解释器将收集到参数和函数信息编译成优化后的机器码,这里就会假定了sum函数的参数就是整形的
      2. 但是如果某次你传入的不是整数,而是字符串,机器不知道如何处理字符串类型的参数,此时就会deoptimization(回退字节码)
      3. 总结:不要把一个变量类型变来变去,传入的参数的类型也要固定一下
posted @ 2020-12-23 18:10  俄罗斯方块  阅读(1193)  评论(0编辑  收藏  举报